summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorMichael Stapelberg <michael@stapelberg.de>2013-03-23 11:28:53 +0100
committerMichael Stapelberg <michael@stapelberg.de>2013-03-23 11:28:53 +0100
commitb39e15dde5ec7b96c15da9faf4ab5892501c1aae (patch)
tree718cede1f6ca97d082c6c40b7dc3f4f6148253c0 /src/cmd
parent04b08da9af0c450d645ab7389d1467308cfc2db8 (diff)
downloadgolang-upstream/1.1_hg20130323.tar.gz
Imported Upstream version 1.1~hg20130323upstream/1.1_hg20130323
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/5g/gsubr.c20
-rw-r--r--src/cmd/5l/asm.c57
-rw-r--r--src/cmd/5l/l.h8
-rw-r--r--src/cmd/5l/obj.c11
-rw-r--r--src/cmd/6a/lex.c3
-rw-r--r--src/cmd/6c/swt.c2
-rw-r--r--src/cmd/6g/gsubr.c16
-rw-r--r--src/cmd/6l/6.out.h3
-rw-r--r--src/cmd/6l/asm.c165
-rw-r--r--src/cmd/6l/l.h16
-rw-r--r--src/cmd/6l/obj.c28
-rw-r--r--src/cmd/6l/optab.c20
-rw-r--r--src/cmd/6l/span.c10
-rw-r--r--src/cmd/8a/a.y15
-rw-r--r--src/cmd/8a/lex.c6
-rw-r--r--src/cmd/8a/y.tab.c1572
-rw-r--r--src/cmd/8a/y.tab.h98
-rw-r--r--src/cmd/8c/swt.c2
-rw-r--r--src/cmd/8g/cgen.c2
-rw-r--r--src/cmd/8g/gsubr.c16
-rw-r--r--src/cmd/8l/8.out.h10
-rw-r--r--src/cmd/8l/asm.c185
-rw-r--r--src/cmd/8l/l.h13
-rw-r--r--src/cmd/8l/obj.c29
-rw-r--r--src/cmd/8l/optab.c31
-rw-r--r--src/cmd/8l/span.c19
-rw-r--r--src/cmd/addr2line/main.c19
-rw-r--r--src/cmd/api/goapi.go5
-rw-r--r--src/cmd/cc/dpchk.c22
-rw-r--r--src/cmd/cgo/doc.go16
-rw-r--r--src/cmd/cgo/gcc.go6
-rw-r--r--src/cmd/cgo/main.go4
-rw-r--r--src/cmd/cgo/out.go11
-rw-r--r--src/cmd/dist/build.c53
-rw-r--r--src/cmd/dist/windows.c2
-rw-r--r--src/cmd/fix/netipv6zone.go11
-rw-r--r--src/cmd/fix/netipv6zone_test.go28
-rw-r--r--src/cmd/gc/builtin.c6
-rw-r--r--src/cmd/gc/closure.c179
-rw-r--r--src/cmd/gc/const.c35
-rw-r--r--src/cmd/gc/cplx.c8
-rw-r--r--src/cmd/gc/dcl.c48
-rw-r--r--src/cmd/gc/esc.c13
-rw-r--r--src/cmd/gc/fmt.c6
-rw-r--r--src/cmd/gc/gen.c5
-rw-r--r--src/cmd/gc/go.h11
-rw-r--r--src/cmd/gc/go.y5
-rw-r--r--src/cmd/gc/inl.c31
-rw-r--r--src/cmd/gc/lex.c1
-rw-r--r--src/cmd/gc/obj.c14
-rw-r--r--src/cmd/gc/racewalk.c66
-rw-r--r--src/cmd/gc/range.c4
-rw-r--r--src/cmd/gc/reflect.c31
-rw-r--r--src/cmd/gc/subr.c15
-rw-r--r--src/cmd/gc/swt.c4
-rw-r--r--src/cmd/gc/typecheck.c201
-rw-r--r--src/cmd/gc/walk.c136
-rw-r--r--src/cmd/gc/y.tab.c505
-rw-r--r--src/cmd/go/build.go44
-rw-r--r--src/cmd/go/discovery.go1
-rw-r--r--src/cmd/go/doc.go43
-rw-r--r--src/cmd/go/go11.go10
-rw-r--r--src/cmd/go/main.go11
-rw-r--r--src/cmd/go/pkg.go7
-rwxr-xr-xsrc/cmd/go/test.bash39
-rw-r--r--src/cmd/go/test.go9
-rw-r--r--src/cmd/go/testdata/errmsg/x.go3
-rw-r--r--src/cmd/go/testdata/errmsg/x1_test.go3
-rw-r--r--src/cmd/go/testdata/errmsg/x_test.go3
-rw-r--r--src/cmd/go/vet.go2
-rw-r--r--src/cmd/godoc/doc.go3
-rw-r--r--src/cmd/godoc/godoc.go33
-rw-r--r--src/cmd/ld/data.c334
-rw-r--r--src/cmd/ld/dwarf.c294
-rw-r--r--src/cmd/ld/dwarf_defs.h1
-rw-r--r--src/cmd/ld/elf.c54
-rw-r--r--src/cmd/ld/elf.h2
-rw-r--r--src/cmd/ld/go.c107
-rw-r--r--src/cmd/ld/ldelf.c4
-rw-r--r--src/cmd/ld/ldmacho.c4
-rw-r--r--src/cmd/ld/ldpe.c10
-rw-r--r--src/cmd/ld/lib.c334
-rw-r--r--src/cmd/ld/lib.h47
-rw-r--r--src/cmd/ld/macho.c592
-rw-r--r--src/cmd/ld/macho.h13
-rw-r--r--src/cmd/ld/pe.c14
-rw-r--r--src/cmd/ld/symtab.c20
-rw-r--r--src/cmd/vet/Makefile8
-rw-r--r--src/cmd/vet/asmdecl.go532
-rw-r--r--src/cmd/vet/assign.go44
-rw-r--r--src/cmd/vet/buildtag.go2
-rw-r--r--src/cmd/vet/deadcode.go280
-rw-r--r--src/cmd/vet/doc.go6
-rw-r--r--src/cmd/vet/main.go118
-rw-r--r--src/cmd/vet/method.go2
-rw-r--r--src/cmd/vet/print.go117
-rw-r--r--src/cmd/vet/structtag.go4
-rw-r--r--src/cmd/vet/taglit.go54
-rw-r--r--src/cmd/vet/test_asm.go24
-rw-r--r--src/cmd/vet/test_asm1.s249
-rw-r--r--src/cmd/vet/test_asm2.s253
-rw-r--r--src/cmd/vet/test_asm3.s168
-rw-r--r--src/cmd/vet/test_assign.go20
-rw-r--r--src/cmd/vet/test_deadcode.go2121
-rw-r--r--src/cmd/vet/test_taglit.go34
-rw-r--r--src/cmd/vet/types.go179
-rw-r--r--src/cmd/vet/typestub.go45
-rw-r--r--src/cmd/yacc/yacc.go1
108 files changed, 7773 insertions, 2387 deletions
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index 191c755b8..d049ebe05 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -543,6 +543,7 @@ ismem(Node *n)
case OINDREG:
case ONAME:
case OPARAM:
+ case OCLOSUREVAR:
return 1;
}
return 0;
@@ -1163,11 +1164,11 @@ gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs)
// Generate an instruction referencing *n
// to force segv on nil pointer dereference.
void
-checkref(Node *n)
+checkref(Node *n, int force)
{
Node m1, m2;
- if(n->type->type->width < unmappedzero)
+ if(!force && isptr[n->type->etype] && n->type->type->width < unmappedzero)
return;
regalloc(&m1, types[TUINTPTR], n);
@@ -1209,8 +1210,6 @@ checkoffset(Addr *a, int canemitcode)
void
naddr(Node *n, Addr *a, int canemitcode)
{
- Prog *p;
-
a->type = D_NONE;
a->name = D_NONE;
a->reg = NREG;
@@ -1283,16 +1282,9 @@ naddr(Node *n, Addr *a, int canemitcode)
break;
case OCLOSUREVAR:
- if(!canemitcode)
- fatal("naddr OCLOSUREVAR cannot emit code");
- p = gins(AMOVW, N, N);
- p->from.type = D_OREG;
- p->from.reg = 7;
- p->from.offset = n->xoffset;
- p->to.type = D_REG;
- p->to.reg = 1;
- a->type = D_REG;
- a->reg = 1;
+ a->type = D_OREG;
+ a->reg = 7;
+ a->offset = n->xoffset;
a->sym = S;
break;
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 04f2a9c6c..a1220a38e 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -125,7 +125,7 @@ adddynrel(Sym *s, Reloc *r)
// Handle relocations found in ELF object files.
case 256 + R_ARM_PLT32:
r->type = D_CALL;
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = braddoff(r->add, targ->plt / 4);
@@ -138,7 +138,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_ARM_GOT32: // R_ARM_GOT_BREL
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
addgotsyminternal(targ);
} else {
addgotsym(targ);
@@ -149,7 +149,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_ARM_GOT_PREL: // GOT(S) + A - P
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
addgotsyminternal(targ);
} else {
addgotsym(targ);
@@ -171,7 +171,7 @@ adddynrel(Sym *s, Reloc *r)
case 256 + R_ARM_CALL:
r->type = D_CALL;
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = braddoff(r->add, targ->plt / 4);
@@ -184,7 +184,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_ARM_ABS32:
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected R_ARM_ABS32 relocation for dynamic symbol %s", targ->name);
r->type = D_ADDR;
return;
@@ -201,7 +201,7 @@ adddynrel(Sym *s, Reloc *r)
case 256 + R_ARM_PC24:
case 256 + R_ARM_JUMP24:
r->type = D_CALL;
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = braddoff(r->add, targ->plt / 4);
@@ -210,7 +210,7 @@ adddynrel(Sym *s, Reloc *r)
}
// Handle references to ELF symbols from our own object files.
- if(targ->dynimpname == nil || targ->dynexport)
+ if(targ->type != SDYNIMPORT)
return;
switch(r->type) {
@@ -240,12 +240,13 @@ adddynrel(Sym *s, Reloc *r)
}
int
-elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+elfreloc1(Reloc *r, vlong sectoff)
{
- USED(add); // written to obj file by ../ld/data.c's reloc
-
- LPUT(off);
+ int32 elfsym;
+
+ LPUT(sectoff);
+ elfsym = r->xsym->elfsym;
switch(r->type) {
default:
return -1;
@@ -295,6 +296,16 @@ elfsetupplt(void)
}
int
+machoreloc1(Reloc *r, vlong sectoff)
+{
+ USED(r);
+ USED(sectoff);
+
+ return -1;
+}
+
+
+int
archreloc(Reloc *r, Sym *s, vlong *val)
{
switch(r->type) {
@@ -324,15 +335,16 @@ archreloc(Reloc *r, Sym *s, vlong *val)
*val = braddoff((0xff000000U & (uint32)r->add),
(0xffffff & (uint32)
((symaddr(r->sym) + ((uint32)r->add) * 4 - (s->value + r->off)) / 4)));
- return 0;
-}
-return -1;
+ return 0;
+ }
+ return -1;
}
static Reloc *
addpltreloc(Sym *plt, Sym *got, Sym *sym, int typ)
{
-Reloc *r;
+ Reloc *r;
+
r = addrel(plt);
r->sym = got;
r->off = plt->size;
@@ -437,20 +449,13 @@ adddynsym(Sym *s)
if(s->dynid >= 0)
return;
- if(s->dynimpname == nil) {
- s->dynimpname = s->name;
- //diag("adddynsym: no dynamic name for %s", s->name);
- }
-
if(iself) {
s->dynid = nelfsym++;
d = lookup(".dynsym", 0);
/* name */
- name = s->dynimpname;
- if(name == nil)
- name = s->name;
+ name = s->extname;
adduint32(d, addstring(lookup(".dynstr", 0), name));
/* value */
@@ -464,7 +469,7 @@ adddynsym(Sym *s)
/* type */
t = STB_GLOBAL << 4;
- if(s->dynexport && (s->type&SMASK) == STEXT)
+ if((s->cgoexport & CgoExportDynamic) && (s->type&SMASK) == STEXT)
t |= STT_FUNC;
else
t |= STT_OBJECT;
@@ -472,7 +477,7 @@ adddynsym(Sym *s)
adduint8(d, 0);
/* shndx */
- if(!s->dynexport && s->dynimpname != nil)
+ if(s->type == SDYNIMPORT)
adduint16(d, SHN_UNDEF);
else {
switch(s->type) {
@@ -600,7 +605,7 @@ asmb(void)
Bprint(&bso, "%5.2f dwarf\n", cputime());
dwarfemitdebugsections();
- if(isobj)
+ if(linkmode == LinkExternal)
elfemitreloc();
}
break;
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index 62dd8947f..83c8b755c 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -38,6 +38,7 @@ enum
thechar = '5',
PtrSize = 4,
IntSize = 4,
+ MaxAlign = 8, // max data alignment
FuncAlign = 4 // single-instruction alignment
};
@@ -95,9 +96,12 @@ struct Reloc
{
int32 off;
uchar siz;
+ uchar done;
int16 type;
int32 add;
+ int32 xadd;
Sym* sym;
+ Sym* xsym;
};
struct Prog
@@ -133,11 +137,12 @@ struct Prog
struct Sym
{
char* name;
+ char* extname; // name used in external object files
short type;
short version;
uchar dupok;
uchar reachable;
- uchar dynexport;
+ uchar cgoexport;
uchar leaf;
int32 dynid;
int32 plt;
@@ -162,7 +167,6 @@ struct Sym
Sym* reachparent;
Sym* queue;
char* file;
- char* dynimpname;
char* dynimplib;
char* dynimpvers;
struct Section* sect;
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index 6aa7fdd69..1bcf436c4 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -82,6 +82,7 @@ main(int argc, char *argv[])
INITRND = -1;
INITENTRY = 0;
LIBINITENTRY = 0;
+ linkmode = LinkInternal; // TODO: LinkAuto once everything works.
nuxiinit();
p = getgoarm();
@@ -116,22 +117,30 @@ main(int argc, char *argv[])
flagcount("f", "ignore version mismatch", &debug['f']);
flagcount("g", "disable go package data checks", &debug['g']);
flagstr("k", "sym: set field tracking symbol", &tracksym);
+ flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
flagcount("n", "dump symbol table", &debug['n']);
flagstr("o", "outfile: set output file", &outfile);
flagcount("p", "insert profiling code", &debug['p']);
flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
flagcount("race", "enable race detector", &flag_race);
flagcount("s", "disable symbol table", &debug['s']);
+ flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
flagcount("u", "reject unsafe packages", &debug['u']);
flagcount("v", "print link trace", &debug['v']);
flagcount("w", "disable DWARF generation", &debug['w']);
flagcount("shared", "generate shared object", &flag_shared);
+ // TODO: link mode flag
flagparse(&argc, &argv, usage);
if(argc != 1)
usage();
+ if(linkmode != LinkInternal) {
+ diag("only -linkmode=internal is supported");
+ errorexit();
+ }
+
libinit();
if(HEADTYPE == -1)
@@ -268,6 +277,7 @@ main(int argc, char *argv[])
reloc();
asmb();
undef();
+ hostlink();
if(debug['c'])
print("ARM size = %d\n", armsize);
@@ -424,6 +434,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
ntext = 0;
eof = Boffset(f) + len;
src[0] = 0;
+ pn = estrdup(pn); // we keep it in Sym* references
newloop:
memset(h, 0, sizeof(h));
diff --git a/src/cmd/6a/lex.c b/src/cmd/6a/lex.c
index d65802a20..c969e98e5 100644
--- a/src/cmd/6a/lex.c
+++ b/src/cmd/6a/lex.c
@@ -932,6 +932,8 @@ struct
"PCMPGTW", LTYPE3, APCMPGTW,
"PEXTRW", LTYPEX, APEXTRW,
"PINSRW", LTYPEX, APINSRW,
+ "PINSRD", LTYPEX, APINSRD,
+ "PINSRQ", LTYPEX, APINSRQ,
"PMADDWL", LTYPE3, APMADDWL,
"PMAXSW", LTYPE3, APMAXSW,
"PMAXUB", LTYPE3, APMAXUB,
@@ -949,6 +951,7 @@ struct
"PSHUFL", LTYPEX, APSHUFL,
"PSHUFLW", LTYPEX, APSHUFLW,
"PSHUFW", LTYPEX, APSHUFW,
+ "PSHUFB", LTYPEM, APSHUFB,
"PSLLO", LTYPE3, APSLLO,
"PSLLDQ", LTYPE3, APSLLO, /* syn */
"PSLLL", LTYPE3, APSLLL,
diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c
index 58d6d5129..541c7beaa 100644
--- a/src/cmd/6c/swt.c
+++ b/src/cmd/6c/swt.c
@@ -320,7 +320,7 @@ outcode(void)
zaddr(&b, &p->from, sf);
zaddr(&b, &p->to, st);
}
- Bflush(&b);
+ Bterm(&b);
close(f);
firstp = P;
lastp = P;
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index fc5407a1f..739983246 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -555,6 +555,7 @@ ismem(Node *n)
case OINDREG:
case ONAME:
case OPARAM:
+ case OCLOSUREVAR:
return 1;
case OADDR:
if(flag_largemodel)
@@ -1057,11 +1058,11 @@ gins(int as, Node *f, Node *t)
// Generate an instruction referencing *n
// to force segv on nil pointer dereference.
void
-checkref(Node *n)
+checkref(Node *n, int force)
{
Node m;
- if(n->type->type->width < unmappedzero)
+ if(!force && isptr[n->type->etype] && n->type->type->width < unmappedzero)
return;
regalloc(&m, types[TUINTPTR], n);
@@ -1098,8 +1099,6 @@ checkoffset(Addr *a, int canemitcode)
void
naddr(Node *n, Addr *a, int canemitcode)
{
- Prog *p;
-
a->scale = 0;
a->index = D_NONE;
a->type = D_NONE;
@@ -1163,14 +1162,9 @@ naddr(Node *n, Addr *a, int canemitcode)
break;
case OCLOSUREVAR:
- if(!canemitcode)
- fatal("naddr OCLOSUREVAR cannot emit code");
- p = gins(AMOVQ, N, N);
- p->from.type = D_DX+D_INDIR;
- p->from.offset = n->xoffset;
- p->to.type = D_BX;
- a->type = D_BX;
+ a->type = D_DX+D_INDIR;
a->sym = S;
+ a->offset = n->xoffset;
break;
case OCFUNC:
diff --git a/src/cmd/6l/6.out.h b/src/cmd/6l/6.out.h
index 805b3fc6f..28de74944 100644
--- a/src/cmd/6l/6.out.h
+++ b/src/cmd/6l/6.out.h
@@ -654,6 +654,8 @@ enum as
APFSUB,
APFSUBR,
APINSRW,
+ APINSRD,
+ APINSRQ,
APMADDWL,
APMAXSW,
APMAXUB,
@@ -671,6 +673,7 @@ enum as
APSHUFL,
APSHUFLW,
APSHUFW,
+ APSHUFB,
APSLLO,
APSLLL,
APSLLQ,
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 5fb75ba4d..07ba59ad9 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -131,7 +131,7 @@ adddynrel(Sym *s, Reloc *r)
// Handle relocations found in ELF object files.
case 256 + R_X86_64_PC32:
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ->name);
if(targ->type == 0 || targ->type == SXREF)
diag("unknown symbol %s in pcrel", targ->name);
@@ -142,7 +142,7 @@ adddynrel(Sym *s, Reloc *r)
case 256 + R_X86_64_PLT32:
r->type = D_PCREL;
r->add += 4;
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add += targ->plt;
@@ -150,7 +150,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_X86_64_GOTPCREL:
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
// have symbol
if(r->off >= 2 && s->p[r->off-2] == 0x8b) {
// turn MOVQ of GOT entry into LEAQ of symbol itself
@@ -161,7 +161,6 @@ adddynrel(Sym *s, Reloc *r)
}
// fall back to using GOT and hope for the best (CMOV*)
// TODO: just needs relocation, no need to put in .dynsym
- targ->dynimpname = targ->name;
}
addgotsym(targ);
r->type = D_PCREL;
@@ -171,7 +170,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_X86_64_64:
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected R_X86_64_64 relocation for dynamic symbol %s", targ->name);
r->type = D_ADDR;
return;
@@ -182,12 +181,12 @@ adddynrel(Sym *s, Reloc *r)
case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 0:
// TODO: What is the difference between all these?
r->type = D_ADDR;
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected reloc for dynamic symbol %s", targ->name);
return;
case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 1:
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = targ->plt;
@@ -201,12 +200,12 @@ adddynrel(Sym *s, Reloc *r)
case 512 + MACHO_X86_64_RELOC_SIGNED_2*2 + 1:
case 512 + MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
r->type = D_PCREL;
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected pc-relative reloc for dynamic symbol %s", targ->name);
return;
case 512 + MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
// have symbol
// turn MOVQ of GOT entry into LEAQ of symbol itself
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
@@ -219,7 +218,7 @@ adddynrel(Sym *s, Reloc *r)
}
// fall through
case 512 + MACHO_X86_64_RELOC_GOT*2 + 1:
- if(targ->dynimpname == nil || targ->dynexport)
+ if(targ->type != SDYNIMPORT)
diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
addgotsym(targ);
r->type = D_PCREL;
@@ -229,7 +228,7 @@ adddynrel(Sym *s, Reloc *r)
}
// Handle references to ELF symbols from our own object files.
- if(targ->dynimpname == nil || targ->dynexport)
+ if(targ->type != SDYNIMPORT)
return;
switch(r->type) {
@@ -285,10 +284,13 @@ adddynrel(Sym *s, Reloc *r)
}
int
-elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+elfreloc1(Reloc *r, vlong sectoff)
{
- VPUT(off);
+ int32 elfsym;
+ VPUT(sectoff);
+
+ elfsym = r->xsym->elfsym;
switch(r->type) {
default:
return -1;
@@ -307,11 +309,67 @@ elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
else
return -1;
- add -= r->siz;
break;
}
- VPUT(add);
+ VPUT(r->xadd);
+ return 0;
+}
+
+int
+machoreloc1(Reloc *r, vlong sectoff)
+{
+ uint32 v;
+ Sym *rs;
+
+ rs = r->xsym;
+
+ if(rs->type == SHOSTOBJ) {
+ if(rs->dynid < 0) {
+ diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type);
+ return -1;
+ }
+ v = rs->dynid;
+ v |= 1<<27; // external relocation
+ } else {
+ v = rs->sect->extnum;
+ if(v == 0) {
+ diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type);
+ return -1;
+ }
+ }
+
+ switch(r->type) {
+ default:
+ return -1;
+ case D_ADDR:
+ v |= MACHO_X86_64_RELOC_UNSIGNED<<28;
+ break;
+ case D_PCREL:
+ v |= 1<<24; // pc-relative bit
+ v |= MACHO_X86_64_RELOC_BRANCH<<28;
+ break;
+ }
+
+ switch(r->siz) {
+ default:
+ return -1;
+ case 1:
+ v |= 0<<25;
+ break;
+ case 2:
+ v |= 1<<25;
+ break;
+ case 4:
+ v |= 2<<25;
+ break;
+ case 8:
+ v |= 3<<25;
+ break;
+ }
+
+ LPUT(sectoff);
+ LPUT(v);
return 0;
}
@@ -448,29 +506,23 @@ addgotsym(Sym *s)
void
adddynsym(Sym *s)
{
- Sym *d, *str;
+ Sym *d;
int t;
char *name;
- vlong off;
if(s->dynid >= 0)
return;
- if(s->dynimpname == nil)
- diag("adddynsym: no dynamic name for %s", s->name);
-
if(iself) {
s->dynid = nelfsym++;
d = lookup(".dynsym", 0);
- name = s->dynimpname;
- if(name == nil)
- name = s->name;
+ name = s->extname;
adduint32(d, addstring(lookup(".dynstr", 0), name));
/* type */
t = STB_GLOBAL << 4;
- if(s->dynexport && (s->type&SMASK) == STEXT)
+ if(s->cgoexport && (s->type&SMASK) == STEXT)
t |= STT_FUNC;
else
t |= STT_OBJECT;
@@ -480,7 +532,7 @@ adddynsym(Sym *s)
adduint8(d, 0);
/* section where symbol is defined */
- if(!s->dynexport && s->dynimpname != nil)
+ if(s->type == SDYNIMPORT)
adduint16(d, SHN_UNDEF);
else {
switch(s->type) {
@@ -510,62 +562,15 @@ adddynsym(Sym *s)
/* size of object */
adduint64(d, s->size);
- if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) {
+ if(!(s->cgoexport & CgoExportDynamic) && s->dynimplib && needlib(s->dynimplib)) {
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED,
addstring(lookup(".dynstr", 0), s->dynimplib));
}
} else if(HEADTYPE == Hdarwin) {
- // Mach-o symbol nlist64
- d = lookup(".dynsym", 0);
- name = s->dynimpname;
- if(name == nil)
- name = s->name;
- if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps
- symgrow(d, ndynexp*16);
- }
- if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp()
- s->dynid = -s->dynid-100;
- off = s->dynid*16;
- } else {
- off = d->size;
- s->dynid = off/16;
- }
- // darwin still puts _ prefixes on all C symbols
- str = lookup(".dynstr", 0);
- setuint32(d, off, str->size);
- off += 4;
- adduint8(str, '_');
- addstring(str, name);
- if(s->type == SDYNIMPORT) {
- setuint8(d, off, 0x01); // type - N_EXT - external symbol
- off++;
- setuint8(d, off, 0); // section
- off++;
- } else {
- setuint8(d, off, 0x0f);
- off++;
- switch(s->type) {
- default:
- case STEXT:
- setuint8(d, off, 1);
- break;
- case SDATA:
- setuint8(d, off, 2);
- break;
- case SBSS:
- setuint8(d, off, 4);
- break;
- }
- off++;
- }
- setuint16(d, off, 0); // desc
- off += 2;
- if(s->type == SDYNIMPORT)
- setuint64(d, off, 0); // value
- else
- setaddr(d, off, s);
- off += 8;
- } else if(HEADTYPE != Hwindows) {
+ diag("adddynsym: missed symbol %s (%s)", s->name, s->extname);
+ } else if(HEADTYPE == Hwindows) {
+ // already taken care of
+ } else {
diag("adddynsym: unsupported binary format");
}
}
@@ -706,7 +711,7 @@ asmb(void)
dwarfemitdebugsections();
- if(isobj)
+ if(linkmode == LinkExternal)
elfemitreloc();
}
break;
@@ -729,6 +734,10 @@ asmb(void)
dwarfemitdebugsections();
break;
+ case Hdarwin:
+ if(linkmode == LinkExternal)
+ machoemitreloc();
+ break;
}
}
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index ffb8a4552..1d6e55c97 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -42,6 +42,7 @@ enum
thechar = '6',
PtrSize = 8,
IntSize = 8,
+ MaxAlign = 32, // max data alignment
// Loop alignment constants:
// want to align loop entry to LoopAlign-byte boundary,
@@ -100,9 +101,12 @@ struct Reloc
{
int32 off;
uchar siz;
+ uchar done;
int32 type;
int64 add;
+ int64 xadd;
Sym* sym;
+ Sym* xsym;
};
struct Prog
@@ -140,11 +144,12 @@ struct Auto
struct Sym
{
char* name;
+ char* extname; // name used in external object files
short type;
short version;
uchar dupok;
uchar reachable;
- uchar dynexport;
+ uchar cgoexport;
uchar special;
uchar stkcheck;
uchar hide;
@@ -167,7 +172,6 @@ struct Sym
vlong size;
Sym* gotype;
char* file;
- char* dynimpname;
char* dynimplib;
char* dynimpvers;
struct Section* sect;
@@ -263,6 +267,7 @@ enum
Zo_iw,
Zm_o,
Zm_r,
+ Zm2_r,
Zm_r_xm,
Zm_r_i_xm,
Zm_r_3d,
@@ -292,10 +297,11 @@ enum
P32 = 0x32, /* 32-bit only */
Pe = 0x66, /* operand escape */
Pm = 0x0f, /* 2byte opcode escape */
- Pq = 0xff, /* both escape */
+ Pq = 0xff, /* both escapes: 66 0f */
Pb = 0xfe, /* byte operands */
- Pf2 = 0xf2, /* xmm escape 1 */
- Pf3 = 0xf3, /* xmm escape 2 */
+ Pf2 = 0xf2, /* xmm escape 1: f2 0f */
+ Pf3 = 0xf3, /* xmm escape 2: f3 0f */
+ Pq3 = 0x67, /* xmm escape 3: 66 48 0f */
Pw = 0x48, /* Rex.w */
Py = 0x80, /* defaults to 64-bit mode */
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 10e4a9860..3775df9de 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -83,6 +83,7 @@ main(int argc, char *argv[])
INITRND = -1;
INITENTRY = 0;
LIBINITENTRY = 0;
+ linkmode = LinkInternal; // TODO: LinkAuto once everything works.
nuxiinit();
flagcount("1", "use alternate profiling code", &debug['1']);
@@ -108,7 +109,7 @@ main(int argc, char *argv[])
flagcount("d", "disable dynamic executable", &debug['d']);
flagcount("f", "ignore version mismatch", &debug['f']);
flagcount("g", "disable go package data checks", &debug['g']);
- flagcount("hostobj", "generate host object file", &isobj);
+ flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
flagstr("k", "sym: set field tracking symbol", &tracksym);
flagcount("n", "dump symbol table", &debug['n']);
flagstr("o", "outfile: set output file", &outfile);
@@ -116,10 +117,11 @@ main(int argc, char *argv[])
flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
flagcount("race", "enable race detector", &flag_race);
flagcount("s", "disable symbol table", &debug['s']);
+ flagcount("shared", "generate shared object", &flag_shared);
+ flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
flagcount("u", "reject unsafe packages", &debug['u']);
flagcount("v", "print link trace", &debug['v']);
flagcount("w", "disable DWARF generation", &debug['w']);
- flagcount("shared", "generate shared object", &flag_shared);
flagparse(&argc, &argv, usage);
@@ -131,13 +133,19 @@ main(int argc, char *argv[])
if(HEADTYPE == -1)
HEADTYPE = headtype(goos);
- if(isobj) {
- switch(HEADTYPE) {
- default:
- sysfatal("cannot use -hostobj with -H %s", headstr(HEADTYPE));
- case Hlinux:
- break;
- }
+ switch(HEADTYPE) {
+ default:
+ if(linkmode == LinkAuto)
+ linkmode = LinkInternal;
+ if(linkmode == LinkExternal)
+ sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
+ break;
+ case Hdarwin:
+ case Hfreebsd:
+ case Hlinux:
+ case Hnetbsd:
+ case Hopenbsd:
+ break;
}
if(outfile == nil) {
@@ -282,6 +290,7 @@ main(int argc, char *argv[])
reloc();
asmb();
undef();
+ hostlink();
if(debug['v']) {
Bprint(&bso, "%5.2f cpu time\n", cputime());
Bprint(&bso, "%d symbols\n", nsymbol);
@@ -412,6 +421,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
ntext = 0;
eof = Boffset(f) + len;
src[0] = 0;
+ pn = estrdup(pn); // we keep it in Sym* references
newloop:
memset(h, 0, sizeof(h));
diff --git a/src/cmd/6l/optab.c b/src/cmd/6l/optab.c
index a163e6faa..b0d5ca788 100644
--- a/src/cmd/6l/optab.c
+++ b/src/cmd/6l/optab.c
@@ -522,6 +522,11 @@ uchar ymshuf[] =
Ymm, Ymr, Zibm_r, 2,
0
};
+uchar ymshufb[] =
+{
+ Yxm, Yxr, Zm2_r, 2,
+ 0
+};
uchar yxshuf[] =
{
Yxm, Yxr, Zibm_r, 2,
@@ -532,6 +537,16 @@ uchar yextrw[] =
Yxr, Yrl, Zibm_r, 2,
0
};
+uchar yinsrw[] =
+{
+ Yml, Yxr, Zibm_r, 2,
+ 0
+};
+uchar yinsr[] =
+{
+ Ymm, Yxr, Zibm_r, 3,
+ 0
+};
uchar ypsdq[] =
{
Yi8, Yxr, Zibo_m, 2,
@@ -982,7 +997,9 @@ Optab optab[] =
{ APFRSQRT, ymfp, Px, 0x97 },
{ APFSUB, ymfp, Px, 0x9a },
{ APFSUBR, ymfp, Px, 0xaa },
- { APINSRW, yextrw, Pq, 0xc4,(00) },
+ { APINSRW, yinsrw, Pq, 0xc4,(00) },
+ { APINSRD, yinsr, Pq, 0x3a, 0x22, (00) },
+ { APINSRQ, yinsr, Pq3, 0x3a, 0x22, (00) },
{ APMADDWL, ymm, Py, 0xf5,Pe,0xf5 },
{ APMAXSW, yxm, Pe, 0xee },
{ APMAXUB, yxm, Pe, 0xde },
@@ -1008,6 +1025,7 @@ Optab optab[] =
{ APSHUFL, yxshuf, Pq, 0x70,(00) },
{ APSHUFLW, yxshuf, Pf2, 0x70,(00) },
{ APSHUFW, ymshuf, Pm, 0x70,(00) },
+ { APSHUFB, ymshufb,Pq, 0x38, 0x00 },
{ APSLLO, ypsdq, Pq, 0x73,(07) },
{ APSLLL, yps, Py, 0xf2, 0x72,(06), Pe,0xf2, Pe,0x72,(06) },
{ APSLLQ, yps, Py, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06) },
diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c
index 283a0e349..fa94d8cf9 100644
--- a/src/cmd/6l/span.c
+++ b/src/cmd/6l/span.c
@@ -1161,6 +1161,11 @@ found:
*andptr++ = Pe;
*andptr++ = Pm;
break;
+ case Pq3: /* 16 bit escape, Rex.w, and opcode escape */
+ *andptr++ = Pe;
+ *andptr++ = Pw;
+ *andptr++ = Pm;
+ break;
case Pf2: /* xmm opcode escape */
case Pf3:
@@ -1229,6 +1234,11 @@ found:
*andptr++ = op;
asmand(&p->from, &p->to);
break;
+ case Zm2_r:
+ *andptr++ = op;
+ *andptr++ = o->op[z+1];
+ asmand(&p->from, &p->to);
+ break;
case Zm_r_xm:
mediaop(o, op, t[3], z);
diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y
index 60707d1c9..516e5fbe7 100644
--- a/src/cmd/8a/a.y
+++ b/src/cmd/8a/a.y
@@ -54,7 +54,7 @@
%left '*' '/' '%'
%token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
%token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG LTYPEXC
-%token <lval> LCONST LFP LPC LSB
+%token <lval> LTYPEX LCONST LFP LPC LSB
%token <lval> LBREG LLREG LSREG LFREG LXREG
%token <dval> LFCONST
%token <sval> LSCONST LSP
@@ -63,7 +63,7 @@
%type <con2> con2
%type <gen> mem imm imm2 reg nam rel rem rim rom omem nmem
%type <gen2> nonnon nonrel nonrem rimnon rimrem remrim
-%type <gen2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9
+%type <gen2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 spec10
%%
prog:
| prog
@@ -117,6 +117,7 @@ inst:
| LTYPEI spec7 { outcode($1, &$2); }
| LTYPEG spec8 { outcode($1, &$2); }
| LTYPEXC spec9 { outcode($1, &$2); }
+| LTYPEX spec10 { outcode($1, &$2); }
nonnon:
{
@@ -296,6 +297,16 @@ spec9: /* CMPPS/CMPPD */
$$.to.offset = $5;
}
+spec10: /* PINSRD */
+ imm ',' rem ',' reg
+ {
+ $$.from = $3;
+ $$.to = $5;
+ if($1.type != D_CONST)
+ yyerror("illegal constant");
+ $$.to.offset = $1.offset;
+ }
+
rem:
reg
| mem
diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c
index 770ca5a88..b8fc2c03e 100644
--- a/src/cmd/8a/lex.c
+++ b/src/cmd/8a/lex.c
@@ -306,6 +306,7 @@ struct
"CMPXCHGB", LTYPE3, ACMPXCHGB,
"CMPXCHGL", LTYPE3, ACMPXCHGL,
"CMPXCHGW", LTYPE3, ACMPXCHGW,
+ "CPUID", LTYPE0, ACPUID,
"DAA", LTYPE0, ADAA,
"DAS", LTYPE0, ADAS,
"DATA", LTYPED, ADATA,
@@ -408,6 +409,7 @@ struct
"MOVB", LTYPE3, AMOVB,
"MOVL", LTYPEM, AMOVL,
"MOVW", LTYPEM, AMOVW,
+ "MOVQ", LTYPEM, AMOVQ,
"MOVBLSX", LTYPE3, AMOVBLSX,
"MOVBLZX", LTYPE3, AMOVBLZX,
"MOVBWSX", LTYPE3, AMOVBWSX,
@@ -437,6 +439,7 @@ struct
"OUTSL", LTYPE0, AOUTSL,
"OUTSW", LTYPE0, AOUTSW,
"PAUSE", LTYPEN, APAUSE,
+ "PINSRD", LTYPEX, APINSRD,
"POPAL", LTYPE0, APOPAL,
"POPAW", LTYPE0, APOPAW,
"POPFL", LTYPE0, APOPFL,
@@ -687,6 +690,7 @@ struct
"ADDPS", LTYPE3, AADDPS,
"ADDSD", LTYPE3, AADDSD,
"ADDSS", LTYPE3, AADDSS,
+ "AESENC", LTYPE3, AAESENC,
"ANDNPD", LTYPE3, AANDNPD,
"ANDNPS", LTYPE3, AANDNPS,
"ANDPD", LTYPE3, AANDPD,
@@ -755,11 +759,13 @@ struct
"ORPD", LTYPE3, AORPD,
"ORPS", LTYPE3, AORPS,
"PADDQ", LTYPE3, APADDQ,
+ "PAND", LTYPE3, APAND,
"PMAXSW", LTYPE3, APMAXSW,
"PMAXUB", LTYPE3, APMAXUB,
"PMINSW", LTYPE3, APMINSW,
"PMINUB", LTYPE3, APMINUB,
"PSADBW", LTYPE3, APSADBW,
+ "PSHUFB", LTYPE3, APSHUFB,
"PSUBB", LTYPE3, APSUBB,
"PSUBL", LTYPE3, APSUBL,
"PSUBQ", LTYPE3, APSUBQ,
diff --git a/src/cmd/8a/y.tab.c b/src/cmd/8a/y.tab.c
index 38f2de52d..7eaff0bb0 100644
--- a/src/cmd/8a/y.tab.c
+++ b/src/cmd/8a/y.tab.c
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 2.6.5. */
+/* A Bison parser, made by GNU Bison 2.5. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.6.5"
+#define YYBISON_VERSION "2.5"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -58,11 +58,14 @@
/* Pull parsers. */
#define YYPULL 1
+/* Using locations. */
+#define YYLSP_NEEDED 0
/* Copy the first part of user declarations. */
-/* Line 360 of yacc.c */
+
+/* Line 268 of yacc.c */
#line 31 "a.y"
#include <u.h>
@@ -70,16 +73,14 @@
#include <libc.h>
#include "a.h"
-/* Line 360 of yacc.c */
-#line 75 "y.tab.c"
-# ifndef YY_NULL
-# if defined __cplusplus && 201103L <= __cplusplus
-# define YY_NULL nullptr
-# else
-# define YY_NULL 0
-# endif
-# endif
+/* Line 268 of yacc.c */
+#line 79 "y.tab.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
/* Enabling verbose error messages. */
#ifdef YYERROR_VERBOSE
@@ -89,18 +90,12 @@
# define YYERROR_VERBOSE 0
#endif
-/* In a future release of Bison, this section will be replaced
- by #include "y.tab.h". */
-#ifndef YY_YY_Y_TAB_H_INCLUDED
-# define YY_YY_Y_TAB_H_INCLUDED
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
#endif
+
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -122,21 +117,22 @@ extern int yydebug;
LTYPEI = 270,
LTYPEG = 271,
LTYPEXC = 272,
- LCONST = 273,
- LFP = 274,
- LPC = 275,
- LSB = 276,
- LBREG = 277,
- LLREG = 278,
- LSREG = 279,
- LFREG = 280,
- LXREG = 281,
- LFCONST = 282,
- LSCONST = 283,
- LSP = 284,
- LNAME = 285,
- LLAB = 286,
- LVAR = 287
+ LTYPEX = 273,
+ LCONST = 274,
+ LFP = 275,
+ LPC = 276,
+ LSB = 277,
+ LBREG = 278,
+ LLREG = 279,
+ LSREG = 280,
+ LFREG = 281,
+ LXREG = 282,
+ LFCONST = 283,
+ LSCONST = 284,
+ LSP = 285,
+ LNAME = 286,
+ LLAB = 287,
+ LVAR = 288
};
#endif
/* Tokens. */
@@ -155,28 +151,31 @@ extern int yydebug;
#define LTYPEI 270
#define LTYPEG 271
#define LTYPEXC 272
-#define LCONST 273
-#define LFP 274
-#define LPC 275
-#define LSB 276
-#define LBREG 277
-#define LLREG 278
-#define LSREG 279
-#define LFREG 280
-#define LXREG 281
-#define LFCONST 282
-#define LSCONST 283
-#define LSP 284
-#define LNAME 285
-#define LLAB 286
-#define LVAR 287
+#define LTYPEX 273
+#define LCONST 274
+#define LFP 275
+#define LPC 276
+#define LSB 277
+#define LBREG 278
+#define LLREG 279
+#define LSREG 280
+#define LFREG 281
+#define LXREG 282
+#define LFCONST 283
+#define LSCONST 284
+#define LSP 285
+#define LNAME 286
+#define LLAB 287
+#define LVAR 288
+
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
-/* Line 376 of yacc.c */
+
+/* Line 293 of yacc.c */
#line 37 "a.y"
Sym *sym;
@@ -191,7 +190,8 @@ typedef union YYSTYPE
Gen2 gen2;
-/* Line 376 of yacc.c */
+
+/* Line 293 of yacc.c */
#line 196 "y.tab.c"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
@@ -199,28 +199,12 @@ typedef union YYSTYPE
# define YYSTYPE_IS_DECLARED 1
#endif
-extern YYSTYPE yylval;
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !YY_YY_Y_TAB_H_INCLUDED */
/* Copy the second part of user declarations. */
-/* Line 379 of yacc.c */
-#line 224 "y.tab.c"
+
+/* Line 343 of yacc.c */
+#line 208 "y.tab.c"
#ifdef short
# undef short
@@ -273,24 +257,24 @@ typedef short int yytype_int16;
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
# endif
# endif
# ifndef YY_
-# define YY_(Msgid) Msgid
+# define YY_(msgid) msgid
# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
+# define YYUSE(e) ((void) (e))
#else
-# define YYUSE(E) /* empty */
+# define YYUSE(e) /* empty */
#endif
/* Identity function, used to suppress warnings about constant conditions. */
#ifndef lint
-# define YYID(N) (N)
+# define YYID(n) (n)
#else
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
@@ -326,7 +310,6 @@ YYID (yyi)
# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
- /* Use EXIT_SUCCESS as a witness for stdlib.h. */
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
# endif
@@ -418,20 +401,20 @@ union yyalloc
#endif
#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from SRC to DST. The source and destination do
+/* Copy COUNT objects from FROM to TO. The source and destination do
not overlap. */
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(Dst, Src, Count) \
- __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
# else
-# define YYCOPY(Dst, Src, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (Dst)[yyi] = (Src)[yyi]; \
- } \
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
while (YYID (0))
# endif
# endif
@@ -440,20 +423,20 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 544
+#define YYLAST 553
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 51
+#define YYNTOKENS 52
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 38
+#define YYNNTS 39
/* YYNRULES -- Number of rules. */
-#define YYNRULES 128
+#define YYNRULES 130
/* YYNRULES -- Number of states. */
-#define YYNSTATES 255
+#define YYNSTATES 262
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 287
+#define YYMAXUTOK 288
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -464,16 +447,16 @@ static const yytype_uint8 yytranslate[] =
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 49, 12, 5, 2,
- 47, 48, 10, 8, 46, 9, 2, 11, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 43, 44,
- 6, 45, 7, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 50, 12, 5, 2,
+ 48, 49, 10, 8, 47, 9, 2, 11, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 44, 45,
+ 6, 46, 7, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 4, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 3, 2, 50, 2, 2, 2,
+ 2, 2, 2, 2, 3, 2, 51, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -489,7 +472,7 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 1, 2, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 41, 42
+ 35, 36, 37, 38, 39, 40, 41, 42, 43
};
#if YYDEBUG
@@ -500,65 +483,67 @@ static const yytype_uint16 yyprhs[] =
0, 0, 3, 4, 5, 9, 10, 15, 16, 21,
23, 26, 29, 33, 37, 40, 43, 46, 49, 52,
55, 58, 61, 64, 67, 70, 73, 76, 79, 82,
- 83, 85, 89, 93, 96, 98, 101, 103, 106, 108,
- 112, 118, 122, 128, 131, 133, 136, 138, 140, 144,
- 150, 154, 160, 163, 165, 169, 173, 179, 185, 187,
- 189, 191, 193, 196, 199, 201, 203, 205, 207, 209,
- 214, 217, 220, 222, 224, 226, 228, 230, 232, 235,
- 238, 241, 244, 249, 255, 259, 262, 264, 267, 271,
- 276, 278, 280, 282, 287, 292, 299, 309, 313, 317,
- 322, 328, 337, 339, 346, 352, 360, 361, 364, 367,
- 369, 371, 373, 375, 377, 380, 383, 386, 390, 392,
- 396, 400, 404, 408, 412, 417, 422, 426, 430
+ 85, 86, 88, 92, 96, 99, 101, 104, 106, 109,
+ 111, 115, 121, 125, 131, 134, 136, 139, 141, 143,
+ 147, 153, 157, 163, 166, 168, 172, 176, 182, 188,
+ 194, 196, 198, 200, 202, 205, 208, 210, 212, 214,
+ 216, 218, 223, 226, 229, 231, 233, 235, 237, 239,
+ 241, 244, 247, 250, 253, 258, 264, 268, 271, 273,
+ 276, 280, 285, 287, 289, 291, 296, 301, 308, 318,
+ 322, 326, 331, 337, 346, 348, 355, 361, 369, 370,
+ 373, 376, 378, 380, 382, 384, 386, 389, 392, 395,
+ 399, 401, 405, 409, 413, 417, 421, 426, 431, 435,
+ 439
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
- 52, 0, -1, -1, -1, 52, 53, 54, -1, -1,
- 41, 43, 55, 54, -1, -1, 40, 43, 56, 54,
- -1, 44, -1, 57, 44, -1, 1, 44, -1, 40,
- 45, 88, -1, 42, 45, 88, -1, 13, 58, -1,
- 14, 62, -1, 15, 61, -1, 16, 59, -1, 17,
- 60, -1, 21, 63, -1, 19, 64, -1, 22, 65,
- -1, 18, 66, -1, 20, 67, -1, 23, 68, -1,
- 24, 69, -1, 25, 70, -1, 26, 71, -1, 27,
- 72, -1, -1, 46, -1, 75, 46, 73, -1, 73,
- 46, 75, -1, 75, 46, -1, 75, -1, 46, 73,
- -1, 73, -1, 46, 76, -1, 76, -1, 78, 46,
- 76, -1, 84, 11, 87, 46, 78, -1, 81, 46,
- 79, -1, 81, 46, 87, 46, 79, -1, 46, 74,
- -1, 74, -1, 10, 84, -1, 58, -1, 62, -1,
- 75, 46, 73, -1, 75, 46, 73, 43, 33, -1,
- 75, 46, 73, -1, 75, 46, 73, 43, 34, -1,
- 75, 46, -1, 75, -1, 75, 46, 73, -1, 81,
- 46, 78, -1, 81, 46, 87, 46, 78, -1, 77,
- 46, 73, 46, 87, -1, 77, -1, 81, -1, 76,
- -1, 83, -1, 10, 77, -1, 10, 82, -1, 77,
- -1, 82, -1, 78, -1, 73, -1, 78, -1, 87,
- 47, 30, 48, -1, 40, 85, -1, 41, 85, -1,
- 32, -1, 35, -1, 33, -1, 36, -1, 39, -1,
- 34, -1, 49, 87, -1, 49, 84, -1, 49, 38,
- -1, 49, 37, -1, 49, 47, 37, 48, -1, 49,
- 47, 9, 37, 48, -1, 49, 9, 37, -1, 49,
- 80, -1, 28, -1, 9, 28, -1, 28, 9, 28,
- -1, 9, 28, 9, 28, -1, 82, -1, 83, -1,
- 87, -1, 87, 47, 33, 48, -1, 87, 47, 39,
- 48, -1, 87, 47, 33, 10, 87, 48, -1, 87,
- 47, 33, 48, 47, 33, 10, 87, 48, -1, 47,
- 33, 48, -1, 47, 39, 48, -1, 87, 47, 34,
- 48, -1, 47, 33, 10, 87, 48, -1, 47, 33,
- 48, 47, 33, 10, 87, 48, -1, 84, -1, 84,
- 47, 33, 10, 87, 48, -1, 40, 85, 47, 86,
- 48, -1, 40, 6, 7, 85, 47, 31, 48, -1,
- -1, 8, 87, -1, 9, 87, -1, 31, -1, 39,
- -1, 29, -1, 28, -1, 42, -1, 9, 87, -1,
- 8, 87, -1, 50, 87, -1, 47, 88, 48, -1,
- 87, -1, 88, 8, 88, -1, 88, 9, 88, -1,
- 88, 10, 88, -1, 88, 11, 88, -1, 88, 12,
- 88, -1, 88, 6, 6, 88, -1, 88, 7, 7,
- 88, -1, 88, 5, 88, -1, 88, 4, 88, -1,
- 88, 3, 88, -1
+ 53, 0, -1, -1, -1, 53, 54, 55, -1, -1,
+ 42, 44, 56, 55, -1, -1, 41, 44, 57, 55,
+ -1, 45, -1, 58, 45, -1, 1, 45, -1, 41,
+ 46, 90, -1, 43, 46, 90, -1, 13, 59, -1,
+ 14, 63, -1, 15, 62, -1, 16, 60, -1, 17,
+ 61, -1, 21, 64, -1, 19, 65, -1, 22, 66,
+ -1, 18, 67, -1, 20, 68, -1, 23, 69, -1,
+ 24, 70, -1, 25, 71, -1, 26, 72, -1, 27,
+ 73, -1, 28, 74, -1, -1, 47, -1, 77, 47,
+ 75, -1, 75, 47, 77, -1, 77, 47, -1, 77,
+ -1, 47, 75, -1, 75, -1, 47, 78, -1, 78,
+ -1, 80, 47, 78, -1, 86, 11, 89, 47, 80,
+ -1, 83, 47, 81, -1, 83, 47, 89, 47, 81,
+ -1, 47, 76, -1, 76, -1, 10, 86, -1, 59,
+ -1, 63, -1, 77, 47, 75, -1, 77, 47, 75,
+ 44, 34, -1, 77, 47, 75, -1, 77, 47, 75,
+ 44, 35, -1, 77, 47, -1, 77, -1, 77, 47,
+ 75, -1, 83, 47, 80, -1, 83, 47, 89, 47,
+ 80, -1, 79, 47, 75, 47, 89, -1, 80, 47,
+ 75, 47, 79, -1, 79, -1, 83, -1, 78, -1,
+ 85, -1, 10, 79, -1, 10, 84, -1, 79, -1,
+ 84, -1, 80, -1, 75, -1, 80, -1, 89, 48,
+ 31, 49, -1, 41, 87, -1, 42, 87, -1, 33,
+ -1, 36, -1, 34, -1, 37, -1, 40, -1, 35,
+ -1, 50, 89, -1, 50, 86, -1, 50, 39, -1,
+ 50, 38, -1, 50, 48, 38, 49, -1, 50, 48,
+ 9, 38, 49, -1, 50, 9, 38, -1, 50, 82,
+ -1, 29, -1, 9, 29, -1, 29, 9, 29, -1,
+ 9, 29, 9, 29, -1, 84, -1, 85, -1, 89,
+ -1, 89, 48, 34, 49, -1, 89, 48, 40, 49,
+ -1, 89, 48, 34, 10, 89, 49, -1, 89, 48,
+ 34, 49, 48, 34, 10, 89, 49, -1, 48, 34,
+ 49, -1, 48, 40, 49, -1, 89, 48, 35, 49,
+ -1, 48, 34, 10, 89, 49, -1, 48, 34, 49,
+ 48, 34, 10, 89, 49, -1, 86, -1, 86, 48,
+ 34, 10, 89, 49, -1, 41, 87, 48, 88, 49,
+ -1, 41, 6, 7, 87, 48, 32, 49, -1, -1,
+ 8, 89, -1, 9, 89, -1, 32, -1, 40, -1,
+ 30, -1, 29, -1, 43, -1, 9, 89, -1, 8,
+ 89, -1, 51, 89, -1, 48, 90, 49, -1, 89,
+ -1, 90, 8, 90, -1, 90, 9, 90, -1, 90,
+ 10, 90, -1, 90, 11, 90, -1, 90, 12, 90,
+ -1, 90, 6, 6, 90, -1, 90, 7, 7, 90,
+ -1, 90, 5, 90, -1, 90, 4, 90, -1, 90,
+ 3, 90, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
@@ -566,21 +551,22 @@ static const yytype_uint16 yyrline[] =
{
0, 68, 68, 70, 69, 77, 76, 84, 83, 89,
90, 91, 94, 99, 105, 106, 107, 108, 109, 110,
- 111, 112, 113, 114, 115, 116, 117, 118, 119, 122,
- 126, 133, 140, 147, 152, 159, 164, 171, 176, 181,
- 188, 196, 201, 209, 214, 219, 228, 229, 232, 237,
- 247, 252, 262, 267, 272, 279, 284, 292, 300, 301,
- 304, 305, 306, 310, 314, 315, 316, 319, 320, 323,
- 329, 338, 347, 352, 357, 362, 367, 372, 379, 385,
- 396, 402, 408, 414, 420, 428, 437, 442, 447, 452,
- 459, 460, 463, 469, 475, 481, 490, 499, 504, 509,
- 515, 523, 533, 537, 546, 553, 562, 565, 569, 575,
- 576, 580, 583, 584, 588, 592, 596, 600, 606, 607,
- 611, 615, 619, 623, 627, 631, 635, 639, 643
+ 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
+ 123, 127, 134, 141, 148, 153, 160, 165, 172, 177,
+ 182, 189, 197, 202, 210, 215, 220, 229, 230, 233,
+ 238, 248, 253, 263, 268, 273, 280, 285, 293, 301,
+ 311, 312, 315, 316, 317, 321, 325, 326, 327, 330,
+ 331, 334, 340, 349, 358, 363, 368, 373, 378, 383,
+ 390, 396, 407, 413, 419, 425, 431, 439, 448, 453,
+ 458, 463, 470, 471, 474, 480, 486, 492, 501, 510,
+ 515, 520, 526, 534, 544, 548, 557, 564, 573, 576,
+ 580, 586, 587, 591, 594, 595, 599, 603, 607, 611,
+ 617, 618, 622, 626, 630, 634, 638, 642, 646, 650,
+ 654
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || 0
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
@@ -588,14 +574,15 @@ static const char *const yytname[] =
"$end", "error", "$undefined", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'",
"'-'", "'*'", "'/'", "'%'", "LTYPE0", "LTYPE1", "LTYPE2", "LTYPE3",
"LTYPE4", "LTYPEC", "LTYPED", "LTYPEN", "LTYPER", "LTYPET", "LTYPES",
- "LTYPEM", "LTYPEI", "LTYPEG", "LTYPEXC", "LCONST", "LFP", "LPC", "LSB",
- "LBREG", "LLREG", "LSREG", "LFREG", "LXREG", "LFCONST", "LSCONST", "LSP",
- "LNAME", "LLAB", "LVAR", "':'", "';'", "'='", "','", "'('", "')'", "'$'",
- "'~'", "$accept", "prog", "$@1", "line", "$@2", "$@3", "inst", "nonnon",
- "rimrem", "remrim", "rimnon", "nonrem", "nonrel", "spec1", "spec2",
- "spec3", "spec4", "spec5", "spec6", "spec7", "spec8", "spec9", "rem",
- "rom", "rim", "rel", "reg", "imm", "imm2", "con2", "mem", "omem", "nmem",
- "nam", "offset", "pointer", "con", "expr", YY_NULL
+ "LTYPEM", "LTYPEI", "LTYPEG", "LTYPEXC", "LTYPEX", "LCONST", "LFP",
+ "LPC", "LSB", "LBREG", "LLREG", "LSREG", "LFREG", "LXREG", "LFCONST",
+ "LSCONST", "LSP", "LNAME", "LLAB", "LVAR", "':'", "';'", "'='", "','",
+ "'('", "')'", "'$'", "'~'", "$accept", "prog", "$@1", "line", "$@2",
+ "$@3", "inst", "nonnon", "rimrem", "remrim", "rimnon", "nonrem",
+ "nonrel", "spec1", "spec2", "spec3", "spec4", "spec5", "spec6", "spec7",
+ "spec8", "spec9", "spec10", "rem", "rom", "rim", "rel", "reg", "imm",
+ "imm2", "con2", "mem", "omem", "nmem", "nam", "offset", "pointer", "con",
+ "expr", 0
};
#endif
@@ -608,27 +595,28 @@ static const yytype_uint16 yytoknum[] =
42, 47, 37, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
- 285, 286, 287, 58, 59, 61, 44, 40, 41, 36,
- 126
+ 285, 286, 287, 288, 58, 59, 61, 44, 40, 41,
+ 36, 126
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 51, 52, 53, 52, 55, 54, 56, 54, 54,
- 54, 54, 57, 57, 57, 57, 57, 57, 57, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 58,
- 58, 59, 60, 61, 61, 62, 62, 63, 63, 63,
- 64, 65, 65, 66, 66, 66, 67, 67, 68, 68,
- 69, 69, 70, 70, 70, 71, 71, 72, 73, 73,
- 74, 74, 74, 74, 74, 74, 74, 75, 75, 76,
- 76, 76, 77, 77, 77, 77, 77, 77, 78, 78,
- 78, 78, 78, 78, 78, 79, 80, 80, 80, 80,
- 81, 81, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 83, 83, 84, 84, 85, 85, 85, 86,
- 86, 86, 87, 87, 87, 87, 87, 87, 88, 88,
- 88, 88, 88, 88, 88, 88, 88, 88, 88
+ 0, 52, 53, 54, 53, 56, 55, 57, 55, 55,
+ 55, 55, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 59, 59, 60, 61, 62, 62, 63, 63, 64, 64,
+ 64, 65, 66, 66, 67, 67, 67, 68, 68, 69,
+ 69, 70, 70, 71, 71, 71, 72, 72, 73, 74,
+ 75, 75, 76, 76, 76, 76, 76, 76, 76, 77,
+ 77, 78, 78, 78, 79, 79, 79, 79, 79, 79,
+ 80, 80, 80, 80, 80, 80, 80, 81, 82, 82,
+ 82, 82, 83, 83, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 85, 85, 86, 86, 87, 87,
+ 87, 88, 88, 88, 89, 89, 89, 89, 89, 89,
+ 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
+ 90
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
@@ -636,17 +624,18 @@ static const yytype_uint8 yyr2[] =
{
0, 2, 0, 0, 3, 0, 4, 0, 4, 1,
2, 2, 3, 3, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
- 1, 3, 3, 2, 1, 2, 1, 2, 1, 3,
- 5, 3, 5, 2, 1, 2, 1, 1, 3, 5,
- 3, 5, 2, 1, 3, 3, 5, 5, 1, 1,
- 1, 1, 2, 2, 1, 1, 1, 1, 1, 4,
- 2, 2, 1, 1, 1, 1, 1, 1, 2, 2,
- 2, 2, 4, 5, 3, 2, 1, 2, 3, 4,
- 1, 1, 1, 4, 4, 6, 9, 3, 3, 4,
- 5, 8, 1, 6, 5, 7, 0, 2, 2, 1,
- 1, 1, 1, 1, 2, 2, 2, 3, 1, 3,
- 3, 3, 3, 3, 4, 4, 3, 3, 3
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 1, 3, 3, 2, 1, 2, 1, 2, 1,
+ 3, 5, 3, 5, 2, 1, 2, 1, 1, 3,
+ 5, 3, 5, 2, 1, 3, 3, 5, 5, 5,
+ 1, 1, 1, 1, 2, 2, 1, 1, 1, 1,
+ 1, 4, 2, 2, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 4, 5, 3, 2, 1, 2,
+ 3, 4, 1, 1, 1, 4, 4, 6, 9, 3,
+ 3, 4, 5, 8, 1, 6, 5, 7, 0, 2,
+ 2, 1, 1, 1, 1, 1, 2, 2, 2, 3,
+ 1, 3, 3, 3, 3, 3, 4, 4, 3, 3,
+ 3
};
/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
@@ -654,243 +643,248 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 2, 3, 1, 0, 0, 29, 0, 0, 0, 0,
- 0, 0, 29, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 9, 4, 0, 11, 30, 14, 0,
- 0, 112, 72, 74, 77, 73, 75, 76, 106, 113,
- 0, 0, 0, 15, 36, 58, 59, 90, 91, 102,
- 92, 0, 16, 67, 34, 68, 17, 0, 18, 0,
- 0, 106, 106, 0, 22, 44, 60, 64, 66, 65,
- 61, 92, 20, 0, 30, 46, 47, 23, 106, 0,
- 0, 19, 38, 0, 0, 21, 0, 24, 0, 25,
- 0, 26, 53, 27, 0, 28, 0, 7, 0, 5,
- 0, 10, 115, 114, 0, 0, 0, 0, 35, 0,
- 0, 118, 0, 116, 0, 0, 0, 81, 80, 0,
- 79, 78, 33, 0, 0, 62, 63, 45, 70, 71,
- 0, 43, 0, 0, 70, 37, 0, 0, 0, 0,
- 0, 52, 0, 0, 0, 12, 0, 13, 106, 107,
- 108, 0, 0, 97, 98, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 117, 0, 0, 0, 0,
- 84, 0, 0, 31, 32, 0, 0, 39, 0, 41,
- 0, 48, 50, 54, 55, 0, 0, 8, 6, 0,
- 111, 109, 110, 0, 0, 0, 128, 127, 126, 0,
- 0, 119, 120, 121, 122, 123, 0, 0, 93, 99,
- 94, 0, 82, 69, 0, 0, 86, 85, 0, 0,
- 0, 0, 0, 0, 104, 100, 0, 124, 125, 0,
- 0, 0, 83, 40, 87, 0, 42, 49, 51, 56,
- 57, 0, 0, 103, 95, 0, 0, 88, 105, 0,
- 0, 89, 101, 0, 96
+ 2, 3, 1, 0, 0, 30, 0, 0, 0, 0,
+ 0, 0, 30, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 4, 0, 11, 31, 14,
+ 0, 0, 114, 74, 76, 79, 75, 77, 78, 108,
+ 115, 0, 0, 0, 15, 37, 60, 61, 92, 93,
+ 104, 94, 0, 16, 69, 35, 70, 17, 0, 18,
+ 0, 0, 108, 108, 0, 22, 45, 62, 66, 68,
+ 67, 63, 94, 20, 0, 31, 47, 48, 23, 108,
+ 0, 0, 19, 39, 0, 0, 21, 0, 24, 0,
+ 25, 0, 26, 54, 27, 0, 28, 0, 29, 0,
+ 7, 0, 5, 0, 10, 117, 116, 0, 0, 0,
+ 0, 36, 0, 0, 120, 0, 118, 0, 0, 0,
+ 83, 82, 0, 81, 80, 34, 0, 0, 64, 65,
+ 46, 72, 73, 0, 44, 0, 0, 72, 38, 0,
+ 0, 0, 0, 0, 53, 0, 0, 0, 0, 12,
+ 0, 13, 108, 109, 110, 0, 0, 99, 100, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 119,
+ 0, 0, 0, 0, 86, 0, 0, 32, 33, 0,
+ 0, 40, 0, 42, 0, 49, 51, 55, 56, 0,
+ 0, 0, 8, 6, 0, 113, 111, 112, 0, 0,
+ 0, 130, 129, 128, 0, 0, 121, 122, 123, 124,
+ 125, 0, 0, 95, 101, 96, 0, 84, 71, 0,
+ 0, 88, 87, 0, 0, 0, 0, 0, 0, 0,
+ 106, 102, 0, 126, 127, 0, 0, 0, 85, 41,
+ 89, 0, 43, 50, 52, 57, 58, 59, 0, 0,
+ 105, 97, 0, 0, 90, 107, 0, 0, 91, 103,
+ 0, 98
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 1, 3, 24, 146, 144, 25, 28, 56, 58,
- 52, 43, 81, 72, 85, 64, 77, 87, 89, 91,
- 93, 95, 53, 65, 54, 66, 45, 55, 179, 217,
- 46, 47, 48, 49, 107, 193, 50, 112
+ -1, 1, 3, 25, 150, 148, 26, 29, 57, 59,
+ 53, 44, 82, 73, 86, 65, 78, 88, 90, 92,
+ 94, 96, 98, 54, 66, 55, 67, 46, 56, 183,
+ 222, 47, 48, 49, 50, 110, 198, 51, 115
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -96
+#define YYPACT_NINF -100
static const yytype_int16 yypact[] =
{
- -96, 34, -96, 158, -38, -30, 267, 288, 288, 338,
- 195, 20, 317, 210, 428, 288, 288, 288, 428, 68,
- -6, 2, 42, -96, -96, 45, -96, -96, -96, 449,
- 449, -96, -96, -96, -96, -96, -96, -96, 127, -96,
- 338, 388, 449, -96, -96, -96, -96, -96, -96, 46,
- 47, 382, -96, -96, 52, -96, -96, 59, -96, 62,
- 338, 127, 19, 238, -96, -96, -96, -96, -96, -96,
- -96, 63, -96, 103, 338, -96, -96, -96, 19, 403,
- 449, -96, -96, 69, 78, -96, 81, -96, 94, -96,
- 97, -96, 98, -96, 102, -96, 111, -96, 449, -96,
- 449, -96, -96, -96, 142, 449, 449, 113, -96, 23,
- 110, -96, 74, -96, 137, 58, 432, -96, -96, 439,
- -96, -96, -96, 338, 288, -96, -96, -96, 113, -96,
- 367, -96, 13, 449, -96, -96, 403, 156, 16, 338,
- 338, 338, 443, 338, 158, 523, 158, 523, 19, -96,
- -96, 11, 449, 140, -96, 449, 449, 449, 182, 194,
- 449, 449, 449, 449, 449, -96, 197, 25, 160, 161,
- -96, 475, 162, -96, -96, 163, 168, -96, 8, -96,
- 169, 173, 174, -96, -96, 175, 176, -96, -96, 177,
- -96, -96, -96, 172, 178, 192, 532, 157, 498, 449,
- 449, 64, 64, -96, -96, -96, 449, 449, 186, -96,
- -96, 191, -96, -96, 200, 215, 244, -96, 205, 222,
- 224, 200, 449, 230, -96, -96, 252, 183, 183, 216,
- 217, 234, -96, -96, 254, 240, -96, -96, -96, -96,
- -96, 221, 449, -96, -96, 271, 255, -96, -96, 236,
- 449, -96, -96, 241, -96
+ -100, 22, -100, 165, -32, -22, 263, 286, 286, 332,
+ 195, -1, 309, 212, 414, 286, 286, 286, 414, 81,
+ 7, -16, 24, -12, -100, -100, -4, -100, -100, -100,
+ 485, 485, -100, -100, -100, -100, -100, -100, -100, 39,
+ -100, 332, 385, 485, -100, -100, -100, -100, -100, -100,
+ 46, 65, 370, -100, -100, 72, -100, -100, 75, -100,
+ 76, 332, 39, 102, 240, -100, -100, -100, -100, -100,
+ -100, -100, 77, -100, 117, 332, -100, -100, -100, 102,
+ 408, 485, -100, -100, 83, 85, -100, 89, -100, 91,
+ -100, 92, -100, 97, -100, 98, -100, 100, -100, 101,
+ -100, 485, -100, 485, -100, -100, -100, 135, 485, 485,
+ 104, -100, -6, 113, -100, 71, -100, 119, 32, 423,
+ -100, -100, 438, -100, -100, -100, 332, 286, -100, -100,
+ -100, 104, -100, 355, -100, 29, 485, -100, -100, 408,
+ 146, 455, 332, 332, 332, 461, 332, 332, 165, 164,
+ 165, 164, 102, -100, -100, 6, 485, 161, -100, 485,
+ 485, 485, 206, 207, 485, 485, 485, 485, 485, -100,
+ 203, 4, 166, 167, -100, 470, 173, -100, -100, 174,
+ 178, -100, 15, -100, 179, 183, 189, -100, -100, 187,
+ 193, 197, -100, -100, 204, -100, -100, -100, 202, 208,
+ 222, 533, 541, 78, 485, 485, 95, 95, -100, -100,
+ -100, 485, 485, 210, -100, -100, 215, -100, -100, 7,
+ 232, 256, -100, 216, 233, 235, 7, 485, 81, 236,
+ -100, -100, 268, 188, 188, 230, 237, 250, -100, -100,
+ 276, 258, -100, -100, -100, -100, -100, -100, 244, 485,
+ -100, -100, 279, 272, -100, -100, 253, 485, -100, -100,
+ 259, -100
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -96, -96, -96, -95, -96, -96, -96, 270, -96, -96,
- -96, 274, -96, -96, -96, -96, -96, -96, -96, -96,
- -96, -96, -2, 227, 6, -12, -1, -8, 73, -96,
- 12, 1, 5, -3, -49, -96, -10, -44
+ -100, -100, -100, -99, -100, -100, -100, 293, -100, -100,
+ -100, 295, -100, -100, -100, -100, -100, -100, -100, -100,
+ -100, -100, -100, 17, 245, 0, -7, -9, -8, 90,
+ -100, 13, 1, -3, -2, -44, -100, -10, -64
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -1
-static const yytype_uint8 yytable[] =
+static const yytype_uint16 yytable[] =
{
- 71, 82, 68, 84, 44, 83, 26, 59, 73, 67,
- 44, 69, 128, 129, 57, 70, 27, 215, 96, 102,
- 103, 88, 90, 92, 29, 30, 86, 105, 106, 134,
- 94, 111, 113, 152, 2, 207, 216, 97, 108, 98,
- 190, 121, 191, 175, 31, 99, 167, 168, 120, 187,
- 192, 188, 169, 71, 145, 68, 147, 127, 39, 125,
- 38, 126, 67, 80, 69, 178, 42, 135, 70, 84,
- 111, 153, 108, 208, 162, 163, 164, 155, 156, 157,
- 158, 159, 160, 161, 162, 163, 164, 100, 111, 101,
- 111, 167, 168, 114, 115, 149, 150, 169, 122, 189,
- 32, 33, 34, 35, 36, 123, 103, 37, 124, 111,
- 132, 196, 197, 198, 133, 136, 201, 202, 203, 204,
- 205, 173, 165, 176, 177, 137, 84, 138, 180, 125,
- 174, 126, 185, 104, 184, 105, 106, 181, 182, 183,
- 139, 186, 194, 140, 141, 111, 111, 111, 142, 148,
- 111, 111, 111, 111, 111, 227, 228, 143, 154, 4,
- 151, 103, 157, 158, 159, 160, 161, 162, 163, 164,
- 166, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 175, 195, 199, 111,
- 111, 160, 161, 162, 163, 164, 229, 230, 20, 21,
- 22, 200, 23, 29, 30, 60, 233, 206, 209, 210,
- 212, 213, 240, 239, 214, 218, 219, 220, 29, 30,
- 224, 221, 222, 31, 223, 226, 225, 32, 33, 34,
- 35, 36, 249, 231, 37, 61, 62, 39, 31, 232,
- 253, 63, 41, 234, 51, 42, 29, 30, 130, 51,
- 78, 62, 39, 235, 178, 237, 79, 80, 238, 51,
- 42, 241, 242, 246, 243, 244, 31, 245, 247, 248,
- 32, 33, 34, 35, 36, 29, 30, 37, 61, 62,
- 39, 250, 75, 251, 252, 41, 76, 51, 42, 254,
- 131, 236, 0, 0, 0, 31, 29, 30, 0, 32,
- 33, 34, 35, 36, 0, 0, 37, 38, 0, 39,
- 0, 0, 0, 40, 41, 0, 31, 42, 0, 0,
- 32, 33, 34, 35, 36, 29, 30, 37, 38, 0,
- 39, 0, 0, 0, 0, 41, 0, 51, 42, 0,
- 0, 0, 0, 0, 0, 31, 29, 30, 0, 32,
- 33, 34, 35, 36, 0, 0, 37, 38, 0, 39,
- 0, 0, 0, 74, 41, 0, 31, 42, 0, 0,
- 32, 33, 34, 35, 36, 29, 30, 37, 38, 0,
- 39, 0, 0, 0, 0, 41, 0, 0, 42, 0,
- 29, 116, 0, 0, 0, 31, 29, 30, 0, 32,
- 33, 34, 35, 36, 0, 0, 37, 0, 0, 39,
- 31, 29, 30, 0, 41, 0, 31, 42, 0, 117,
- 118, 109, 38, 0, 39, 0, 0, 110, 0, 119,
- 39, 31, 42, 0, 0, 80, 29, 30, 42, 0,
- 29, 30, 0, 78, 62, 39, 0, 29, 171, 0,
- 80, 29, 30, 42, 0, 0, 31, 29, 30, 0,
- 31, 0, 0, 0, 0, 0, 0, 31, 38, 170,
- 39, 31, 0, 0, 39, 41, 172, 31, 42, 80,
- 0, 39, 42, 29, 30, 39, 80, 0, 0, 42,
- 80, 39, 51, 42, 0, 0, 80, 0, 0, 42,
- 0, 0, 0, 31, 158, 159, 160, 161, 162, 163,
- 164, 0, 211, 0, 0, 0, 0, 39, 0, 0,
- 0, 0, 80, 0, 0, 42, 155, 156, 157, 158,
- 159, 160, 161, 162, 163, 164, 156, 157, 158, 159,
- 160, 161, 162, 163, 164
+ 72, 68, 69, 85, 156, 84, 83, 71, 58, 74,
+ 97, 70, 99, 27, 212, 89, 91, 93, 131, 132,
+ 105, 106, 2, 45, 220, 28, 60, 87, 100, 45,
+ 101, 95, 114, 116, 103, 137, 195, 149, 196, 151,
+ 39, 104, 124, 157, 221, 107, 197, 108, 109, 192,
+ 123, 193, 128, 213, 72, 68, 69, 52, 111, 130,
+ 179, 71, 129, 171, 172, 70, 171, 172, 102, 173,
+ 85, 114, 173, 138, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 162, 163, 164, 165, 166, 167,
+ 168, 114, 111, 114, 117, 201, 202, 203, 153, 154,
+ 206, 207, 208, 209, 210, 166, 167, 168, 194, 106,
+ 108, 109, 114, 118, 33, 34, 35, 36, 37, 125,
+ 169, 38, 126, 127, 128, 135, 180, 178, 136, 85,
+ 139, 184, 181, 140, 129, 189, 141, 188, 142, 143,
+ 233, 234, 152, 177, 144, 145, 199, 146, 147, 114,
+ 114, 114, 155, 170, 114, 114, 114, 114, 114, 185,
+ 186, 187, 158, 190, 191, 106, 4, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 179, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 114, 114, 164, 165, 166, 167,
+ 168, 235, 236, 30, 31, 61, 21, 22, 23, 200,
+ 24, 239, 204, 211, 205, 214, 215, 246, 245, 247,
+ 30, 31, 217, 218, 32, 219, 223, 224, 33, 34,
+ 35, 36, 37, 225, 226, 38, 62, 63, 40, 256,
+ 227, 32, 64, 42, 228, 52, 43, 260, 30, 31,
+ 133, 230, 229, 79, 63, 40, 232, 231, 237, 80,
+ 81, 240, 52, 43, 238, 241, 182, 243, 248, 32,
+ 244, 30, 31, 33, 34, 35, 36, 37, 249, 250,
+ 38, 62, 63, 40, 252, 253, 251, 254, 42, 257,
+ 52, 43, 32, 255, 30, 31, 33, 34, 35, 36,
+ 37, 258, 259, 38, 39, 76, 40, 77, 261, 134,
+ 41, 42, 0, 242, 43, 32, 0, 30, 31, 33,
+ 34, 35, 36, 37, 0, 0, 38, 39, 0, 40,
+ 0, 0, 0, 0, 42, 0, 52, 43, 32, 0,
+ 30, 31, 33, 34, 35, 36, 37, 0, 0, 38,
+ 39, 0, 40, 0, 0, 0, 75, 42, 0, 0,
+ 43, 32, 0, 30, 31, 33, 34, 35, 36, 37,
+ 0, 0, 38, 39, 0, 40, 0, 0, 30, 119,
+ 42, 0, 0, 43, 32, 0, 0, 0, 33, 34,
+ 35, 36, 37, 30, 31, 38, 0, 0, 40, 32,
+ 0, 0, 0, 42, 0, 0, 43, 0, 120, 121,
+ 0, 39, 0, 40, 32, 0, 30, 31, 122, 112,
+ 0, 43, 30, 31, 0, 113, 0, 0, 40, 0,
+ 0, 30, 31, 81, 0, 0, 43, 32, 0, 0,
+ 0, 0, 0, 32, 0, 0, 30, 175, 0, 79,
+ 63, 40, 32, 0, 0, 39, 81, 40, 0, 43,
+ 0, 174, 42, 30, 31, 43, 40, 32, 0, 30,
+ 31, 81, 0, 0, 43, 0, 176, 0, 30, 31,
+ 0, 40, 0, 0, 32, 0, 81, 0, 0, 43,
+ 32, 0, 0, 30, 31, 0, 0, 0, 40, 32,
+ 0, 0, 0, 81, 40, 182, 43, 0, 216, 81,
+ 0, 52, 43, 40, 32, 0, 0, 0, 81, 0,
+ 0, 43, 0, 0, 0, 0, 0, 0, 40, 0,
+ 0, 0, 0, 81, 0, 0, 43, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 161, 162, 163, 164,
+ 165, 166, 167, 168
};
-#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-96)))
+#define yypact_value_is_default(yystate) \
+ ((yystate) == (-100))
-#define yytable_value_is_error(Yytable_value) \
+#define yytable_value_is_error(yytable_value) \
YYID (0)
static const yytype_int16 yycheck[] =
{
- 10, 13, 10, 13, 6, 13, 44, 9, 11, 10,
- 12, 10, 61, 62, 8, 10, 46, 9, 19, 29,
- 30, 15, 16, 17, 8, 9, 14, 8, 9, 78,
- 18, 41, 42, 10, 0, 10, 28, 43, 40, 45,
- 29, 51, 31, 30, 28, 43, 33, 34, 51, 144,
- 39, 146, 39, 63, 98, 63, 100, 60, 42, 60,
- 40, 60, 63, 47, 63, 49, 50, 79, 63, 79,
- 80, 48, 74, 48, 10, 11, 12, 3, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, 45, 98, 44,
- 100, 33, 34, 47, 47, 105, 106, 39, 46, 148,
- 32, 33, 34, 35, 36, 46, 116, 39, 46, 119,
- 47, 155, 156, 157, 11, 46, 160, 161, 162, 163,
- 164, 123, 48, 133, 136, 47, 136, 46, 138, 130,
- 124, 130, 142, 6, 142, 8, 9, 139, 140, 141,
- 46, 143, 152, 46, 46, 155, 156, 157, 46, 7,
- 160, 161, 162, 163, 164, 199, 200, 46, 48, 1,
- 47, 171, 5, 6, 7, 8, 9, 10, 11, 12,
- 33, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 27, 30, 47, 6, 199,
- 200, 8, 9, 10, 11, 12, 206, 207, 40, 41,
- 42, 7, 44, 8, 9, 10, 214, 10, 48, 48,
- 48, 48, 222, 221, 46, 46, 43, 43, 8, 9,
- 48, 46, 46, 28, 47, 33, 48, 32, 33, 34,
- 35, 36, 242, 47, 39, 40, 41, 42, 28, 48,
- 250, 46, 47, 28, 49, 50, 8, 9, 10, 49,
- 40, 41, 42, 9, 49, 33, 46, 47, 34, 49,
- 50, 31, 10, 9, 48, 48, 28, 33, 28, 48,
- 32, 33, 34, 35, 36, 8, 9, 39, 40, 41,
- 42, 10, 12, 28, 48, 47, 12, 49, 50, 48,
- 63, 218, -1, -1, -1, 28, 8, 9, -1, 32,
- 33, 34, 35, 36, -1, -1, 39, 40, -1, 42,
- -1, -1, -1, 46, 47, -1, 28, 50, -1, -1,
- 32, 33, 34, 35, 36, 8, 9, 39, 40, -1,
- 42, -1, -1, -1, -1, 47, -1, 49, 50, -1,
- -1, -1, -1, -1, -1, 28, 8, 9, -1, 32,
- 33, 34, 35, 36, -1, -1, 39, 40, -1, 42,
- -1, -1, -1, 46, 47, -1, 28, 50, -1, -1,
- 32, 33, 34, 35, 36, 8, 9, 39, 40, -1,
- 42, -1, -1, -1, -1, 47, -1, -1, 50, -1,
- 8, 9, -1, -1, -1, 28, 8, 9, -1, 32,
- 33, 34, 35, 36, -1, -1, 39, -1, -1, 42,
- 28, 8, 9, -1, 47, -1, 28, 50, -1, 37,
- 38, 33, 40, -1, 42, -1, -1, 39, -1, 47,
- 42, 28, 50, -1, -1, 47, 8, 9, 50, -1,
- 8, 9, -1, 40, 41, 42, -1, 8, 9, -1,
- 47, 8, 9, 50, -1, -1, 28, 8, 9, -1,
- 28, -1, -1, -1, -1, -1, -1, 28, 40, 37,
- 42, 28, -1, -1, 42, 47, 37, 28, 50, 47,
- -1, 42, 50, 8, 9, 42, 47, -1, -1, 50,
- 47, 42, 49, 50, -1, -1, 47, -1, -1, 50,
- -1, -1, -1, 28, 6, 7, 8, 9, 10, 11,
- 12, -1, 37, -1, -1, -1, -1, 42, -1, -1,
- -1, -1, 47, -1, -1, 50, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 4, 5, 6, 7,
- 8, 9, 10, 11, 12
+ 10, 10, 10, 13, 10, 13, 13, 10, 8, 11,
+ 19, 10, 20, 45, 10, 15, 16, 17, 62, 63,
+ 30, 31, 0, 6, 9, 47, 9, 14, 44, 12,
+ 46, 18, 42, 43, 46, 79, 30, 101, 32, 103,
+ 41, 45, 52, 49, 29, 6, 40, 8, 9, 148,
+ 52, 150, 61, 49, 64, 64, 64, 50, 41, 61,
+ 31, 64, 61, 34, 35, 64, 34, 35, 44, 40,
+ 80, 81, 40, 80, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 6, 7, 8, 9, 10, 11,
+ 12, 101, 75, 103, 48, 159, 160, 161, 108, 109,
+ 164, 165, 166, 167, 168, 10, 11, 12, 152, 119,
+ 8, 9, 122, 48, 33, 34, 35, 36, 37, 47,
+ 49, 40, 47, 47, 133, 48, 136, 127, 11, 139,
+ 47, 141, 139, 48, 133, 145, 47, 145, 47, 47,
+ 204, 205, 7, 126, 47, 47, 156, 47, 47, 159,
+ 160, 161, 48, 34, 164, 165, 166, 167, 168, 142,
+ 143, 144, 49, 146, 147, 175, 1, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 31, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 204, 205, 8, 9, 10, 11,
+ 12, 211, 212, 8, 9, 10, 41, 42, 43, 48,
+ 45, 219, 6, 10, 7, 49, 49, 227, 226, 228,
+ 8, 9, 49, 49, 29, 47, 47, 44, 33, 34,
+ 35, 36, 37, 44, 47, 40, 41, 42, 43, 249,
+ 47, 29, 47, 48, 47, 50, 51, 257, 8, 9,
+ 10, 49, 48, 41, 42, 43, 34, 49, 48, 47,
+ 48, 29, 50, 51, 49, 9, 50, 34, 32, 29,
+ 35, 8, 9, 33, 34, 35, 36, 37, 10, 49,
+ 40, 41, 42, 43, 34, 9, 49, 29, 48, 10,
+ 50, 51, 29, 49, 8, 9, 33, 34, 35, 36,
+ 37, 29, 49, 40, 41, 12, 43, 12, 49, 64,
+ 47, 48, -1, 223, 51, 29, -1, 8, 9, 33,
+ 34, 35, 36, 37, -1, -1, 40, 41, -1, 43,
+ -1, -1, -1, -1, 48, -1, 50, 51, 29, -1,
+ 8, 9, 33, 34, 35, 36, 37, -1, -1, 40,
+ 41, -1, 43, -1, -1, -1, 47, 48, -1, -1,
+ 51, 29, -1, 8, 9, 33, 34, 35, 36, 37,
+ -1, -1, 40, 41, -1, 43, -1, -1, 8, 9,
+ 48, -1, -1, 51, 29, -1, -1, -1, 33, 34,
+ 35, 36, 37, 8, 9, 40, -1, -1, 43, 29,
+ -1, -1, -1, 48, -1, -1, 51, -1, 38, 39,
+ -1, 41, -1, 43, 29, -1, 8, 9, 48, 34,
+ -1, 51, 8, 9, -1, 40, -1, -1, 43, -1,
+ -1, 8, 9, 48, -1, -1, 51, 29, -1, -1,
+ -1, -1, -1, 29, -1, -1, 8, 9, -1, 41,
+ 42, 43, 29, -1, -1, 41, 48, 43, -1, 51,
+ -1, 38, 48, 8, 9, 51, 43, 29, -1, 8,
+ 9, 48, -1, -1, 51, -1, 38, -1, 8, 9,
+ -1, 43, -1, -1, 29, -1, 48, -1, -1, 51,
+ 29, -1, -1, 8, 9, -1, -1, -1, 43, 29,
+ -1, -1, -1, 48, 43, 50, 51, -1, 38, 48,
+ -1, 50, 51, 43, 29, -1, -1, -1, 48, -1,
+ -1, 51, -1, -1, -1, -1, -1, -1, 43, -1,
+ -1, -1, -1, 48, -1, -1, 51, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 5, 6, 7, 8,
+ 9, 10, 11, 12
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 52, 0, 53, 1, 13, 14, 15, 16, 17,
+ 0, 53, 0, 54, 1, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
- 40, 41, 42, 44, 54, 57, 44, 46, 58, 8,
- 9, 28, 32, 33, 34, 35, 36, 39, 40, 42,
- 46, 47, 50, 62, 73, 77, 81, 82, 83, 84,
- 87, 49, 61, 73, 75, 78, 59, 75, 60, 73,
- 10, 40, 41, 46, 66, 74, 76, 77, 78, 82,
- 83, 87, 64, 84, 46, 58, 62, 67, 40, 46,
- 47, 63, 76, 78, 87, 65, 81, 68, 75, 69,
- 75, 70, 75, 71, 81, 72, 77, 43, 45, 43,
- 45, 44, 87, 87, 6, 8, 9, 85, 73, 33,
- 39, 87, 88, 87, 47, 47, 9, 37, 38, 47,
- 84, 87, 46, 46, 46, 77, 82, 84, 85, 85,
- 10, 74, 47, 11, 85, 76, 46, 47, 46, 46,
- 46, 46, 46, 46, 56, 88, 55, 88, 7, 87,
- 87, 47, 10, 48, 48, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 48, 33, 33, 34, 39,
- 37, 9, 37, 73, 75, 30, 87, 76, 49, 79,
- 87, 73, 73, 73, 78, 87, 73, 54, 54, 85,
- 29, 31, 39, 86, 87, 47, 88, 88, 88, 6,
- 7, 88, 88, 88, 88, 88, 10, 10, 48, 48,
- 48, 37, 48, 48, 46, 9, 28, 80, 46, 43,
- 43, 46, 46, 47, 48, 48, 33, 88, 88, 87,
- 87, 47, 48, 78, 28, 9, 79, 33, 34, 78,
- 87, 31, 10, 48, 48, 33, 9, 28, 48, 87,
- 10, 28, 48, 87, 48
+ 28, 41, 42, 43, 45, 55, 58, 45, 47, 59,
+ 8, 9, 29, 33, 34, 35, 36, 37, 40, 41,
+ 43, 47, 48, 51, 63, 75, 79, 83, 84, 85,
+ 86, 89, 50, 62, 75, 77, 80, 60, 77, 61,
+ 75, 10, 41, 42, 47, 67, 76, 78, 79, 80,
+ 84, 85, 89, 65, 86, 47, 59, 63, 68, 41,
+ 47, 48, 64, 78, 80, 89, 66, 83, 69, 77,
+ 70, 77, 71, 77, 72, 83, 73, 79, 74, 80,
+ 44, 46, 44, 46, 45, 89, 89, 6, 8, 9,
+ 87, 75, 34, 40, 89, 90, 89, 48, 48, 9,
+ 38, 39, 48, 86, 89, 47, 47, 47, 79, 84,
+ 86, 87, 87, 10, 76, 48, 11, 87, 78, 47,
+ 48, 47, 47, 47, 47, 47, 47, 47, 57, 90,
+ 56, 90, 7, 89, 89, 48, 10, 49, 49, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 49,
+ 34, 34, 35, 40, 38, 9, 38, 75, 77, 31,
+ 89, 78, 50, 81, 89, 75, 75, 75, 80, 89,
+ 75, 75, 55, 55, 87, 30, 32, 40, 88, 89,
+ 48, 90, 90, 90, 6, 7, 90, 90, 90, 90,
+ 90, 10, 10, 49, 49, 49, 38, 49, 49, 47,
+ 9, 29, 82, 47, 44, 44, 47, 47, 47, 48,
+ 49, 49, 34, 90, 90, 89, 89, 48, 49, 80,
+ 29, 9, 81, 34, 35, 80, 89, 79, 32, 10,
+ 49, 49, 34, 9, 29, 49, 89, 10, 29, 49,
+ 89, 49
};
#define yyerrok (yyerrstatus = 0)
@@ -920,35 +914,62 @@ static const yytype_uint8 yystos[] =
#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- YYPOPSTACK (yylen); \
- yystate = *yyssp; \
- goto yybackup; \
- } \
- else \
- { \
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
yyerror (YY_("syntax error: cannot back up")); \
YYERROR; \
} \
while (YYID (0))
-/* Error token number */
+
#define YYTERROR 1
#define YYERRCODE 256
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
/* This macro is provided for backward compatibility. */
+
#ifndef YY_LOCATION_PRINT
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
#endif
/* YYLEX -- calling `yylex' with the right arguments. */
+
#ifdef YYLEX_PARAM
# define YYLEX yylex (YYLEX_PARAM)
#else
@@ -998,8 +1019,6 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
YYSTYPE const * const yyvaluep;
#endif
{
- FILE *yyo = yyoutput;
- YYUSE (yyo);
if (!yyvaluep)
return;
# ifdef YYPRINT
@@ -1251,12 +1270,12 @@ static int
yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
yytype_int16 *yyssp, int yytoken)
{
- YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
YYSIZE_T yysize = yysize0;
YYSIZE_T yysize1;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
/* Internationalized format string. */
- const char *yyformat = YY_NULL;
+ const char *yyformat = 0;
/* Arguments of yyformat. */
char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
/* Number of reported tokens (one for the "unexpected", one per
@@ -1316,7 +1335,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
break;
}
yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
if (! (yysize <= yysize1
&& yysize1 <= YYSTACK_ALLOC_MAXIMUM))
return 2;
@@ -1408,22 +1427,27 @@ yydestruct (yymsg, yytype, yyvaluep)
}
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
/* The lookahead symbol. */
int yychar;
-
-#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END
-#endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
-
/* The semantic value of the lookahead symbol. */
-YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
+YYSTYPE yylval;
/* Number of syntax errors so far. */
int yynerrs;
@@ -1463,7 +1487,7 @@ yyparse ()
`yyss': related to states.
`yyvs': related to semantic values.
- Refer to the stacks through separate pointers, to allow yyoverflow
+ Refer to the stacks thru separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
/* The state stack. */
@@ -1481,7 +1505,7 @@ yyparse ()
int yyn;
int yyresult;
/* Lookahead token as an internal (translated) token number. */
- int yytoken = 0;
+ int yytoken;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
@@ -1499,8 +1523,9 @@ yyparse ()
Keep to zero when no symbol should be popped. */
int yylen = 0;
- yyssp = yyss = yyssa;
- yyvsp = yyvs = yyvsa;
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
yystacksize = YYINITDEPTH;
YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1509,6 +1534,14 @@ yyparse ()
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+
goto yysetstate;
/*------------------------------------------------------------.
@@ -1649,9 +1682,7 @@ yybackup:
yychar = YYEMPTY;
yystate = yyn;
- YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
- YY_IGNORE_MAYBE_UNINITIALIZED_END
goto yynewstate;
@@ -1688,7 +1719,8 @@ yyreduce:
switch (yyn)
{
case 3:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 70 "a.y"
{
stmtline = lineno;
@@ -1696,7 +1728,8 @@ yyreduce:
break;
case 5:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 77 "a.y"
{
if((yyvsp[(1) - (2)].sym)->value != pc)
@@ -1706,7 +1739,8 @@ yyreduce:
break;
case 7:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 84 "a.y"
{
(yyvsp[(1) - (2)].sym)->type = LLAB;
@@ -1715,7 +1749,8 @@ yyreduce:
break;
case 12:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 95 "a.y"
{
(yyvsp[(1) - (3)].sym)->type = LVAR;
@@ -1724,7 +1759,8 @@ yyreduce:
break;
case 13:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 100 "a.y"
{
if((yyvsp[(1) - (3)].sym)->value != (yyvsp[(3) - (3)].lval))
@@ -1734,197 +1770,231 @@ yyreduce:
break;
case 14:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 105 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 15:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 106 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 16:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 107 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 17:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 108 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 18:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 109 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 19:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 110 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 20:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 111 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 21:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 112 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 22:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 113 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 23:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 114 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 24:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 115 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 25:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 116 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 26:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 117 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 27:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 118 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 28:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 119 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 29:
-/* Line 1778 of yacc.c */
-#line 122 "a.y"
+
+/* Line 1806 of yacc.c */
+#line 120 "a.y"
+ { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
+ break;
+
+ case 30:
+
+/* Line 1806 of yacc.c */
+#line 123 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = nullgen;
}
break;
- case 30:
-/* Line 1778 of yacc.c */
-#line 127 "a.y"
+ case 31:
+
+/* Line 1806 of yacc.c */
+#line 128 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = nullgen;
}
break;
- case 31:
-/* Line 1778 of yacc.c */
-#line 134 "a.y"
+ case 32:
+
+/* Line 1806 of yacc.c */
+#line 135 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 32:
-/* Line 1778 of yacc.c */
-#line 141 "a.y"
+ case 33:
+
+/* Line 1806 of yacc.c */
+#line 142 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 33:
-/* Line 1778 of yacc.c */
-#line 148 "a.y"
+ case 34:
+
+/* Line 1806 of yacc.c */
+#line 149 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (2)].gen);
(yyval.gen2).to = nullgen;
}
break;
- case 34:
-/* Line 1778 of yacc.c */
-#line 153 "a.y"
+ case 35:
+
+/* Line 1806 of yacc.c */
+#line 154 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (1)].gen);
(yyval.gen2).to = nullgen;
}
break;
- case 35:
-/* Line 1778 of yacc.c */
-#line 160 "a.y"
+ case 36:
+
+/* Line 1806 of yacc.c */
+#line 161 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
}
break;
- case 36:
-/* Line 1778 of yacc.c */
-#line 165 "a.y"
+ case 37:
+
+/* Line 1806 of yacc.c */
+#line 166 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(1) - (1)].gen);
}
break;
- case 37:
-/* Line 1778 of yacc.c */
-#line 172 "a.y"
+ case 38:
+
+/* Line 1806 of yacc.c */
+#line 173 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
}
break;
- case 38:
-/* Line 1778 of yacc.c */
-#line 177 "a.y"
+ case 39:
+
+/* Line 1806 of yacc.c */
+#line 178 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(1) - (1)].gen);
}
break;
- case 39:
-/* Line 1778 of yacc.c */
-#line 182 "a.y"
+ case 40:
+
+/* Line 1806 of yacc.c */
+#line 183 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 40:
-/* Line 1778 of yacc.c */
-#line 189 "a.y"
+ case 41:
+
+/* Line 1806 of yacc.c */
+#line 190 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -1932,18 +2002,20 @@ yyreduce:
}
break;
- case 41:
-/* Line 1778 of yacc.c */
-#line 197 "a.y"
+ case 42:
+
+/* Line 1806 of yacc.c */
+#line 198 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 42:
-/* Line 1778 of yacc.c */
-#line 202 "a.y"
+ case 43:
+
+/* Line 1806 of yacc.c */
+#line 203 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -1951,27 +2023,30 @@ yyreduce:
}
break;
- case 43:
-/* Line 1778 of yacc.c */
-#line 210 "a.y"
+ case 44:
+
+/* Line 1806 of yacc.c */
+#line 211 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
}
break;
- case 44:
-/* Line 1778 of yacc.c */
-#line 215 "a.y"
+ case 45:
+
+/* Line 1806 of yacc.c */
+#line 216 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(1) - (1)].gen);
}
break;
- case 45:
-/* Line 1778 of yacc.c */
-#line 220 "a.y"
+ case 46:
+
+/* Line 1806 of yacc.c */
+#line 221 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
@@ -1980,18 +2055,20 @@ yyreduce:
}
break;
- case 48:
-/* Line 1778 of yacc.c */
-#line 233 "a.y"
+ case 49:
+
+/* Line 1806 of yacc.c */
+#line 234 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 49:
-/* Line 1778 of yacc.c */
-#line 238 "a.y"
+ case 50:
+
+/* Line 1806 of yacc.c */
+#line 239 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
@@ -2001,18 +2078,20 @@ yyreduce:
}
break;
- case 50:
-/* Line 1778 of yacc.c */
-#line 248 "a.y"
+ case 51:
+
+/* Line 1806 of yacc.c */
+#line 249 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 51:
-/* Line 1778 of yacc.c */
-#line 253 "a.y"
+ case 52:
+
+/* Line 1806 of yacc.c */
+#line 254 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
@@ -2022,45 +2101,50 @@ yyreduce:
}
break;
- case 52:
-/* Line 1778 of yacc.c */
-#line 263 "a.y"
+ case 53:
+
+/* Line 1806 of yacc.c */
+#line 264 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (2)].gen);
(yyval.gen2).to = nullgen;
}
break;
- case 53:
-/* Line 1778 of yacc.c */
-#line 268 "a.y"
+ case 54:
+
+/* Line 1806 of yacc.c */
+#line 269 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (1)].gen);
(yyval.gen2).to = nullgen;
}
break;
- case 54:
-/* Line 1778 of yacc.c */
-#line 273 "a.y"
+ case 55:
+
+/* Line 1806 of yacc.c */
+#line 274 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 55:
-/* Line 1778 of yacc.c */
-#line 280 "a.y"
+ case 56:
+
+/* Line 1806 of yacc.c */
+#line 281 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 56:
-/* Line 1778 of yacc.c */
-#line 285 "a.y"
+ case 57:
+
+/* Line 1806 of yacc.c */
+#line 286 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -2068,9 +2152,10 @@ yyreduce:
}
break;
- case 57:
-/* Line 1778 of yacc.c */
-#line 293 "a.y"
+ case 58:
+
+/* Line 1806 of yacc.c */
+#line 294 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
@@ -2078,25 +2163,41 @@ yyreduce:
}
break;
- case 62:
-/* Line 1778 of yacc.c */
-#line 307 "a.y"
+ case 59:
+
+/* Line 1806 of yacc.c */
+#line 302 "a.y"
+ {
+ (yyval.gen2).from = (yyvsp[(3) - (5)].gen);
+ (yyval.gen2).to = (yyvsp[(5) - (5)].gen);
+ if((yyvsp[(1) - (5)].gen).type != D_CONST)
+ yyerror("illegal constant");
+ (yyval.gen2).to.offset = (yyvsp[(1) - (5)].gen).offset;
+ }
+ break;
+
+ case 64:
+
+/* Line 1806 of yacc.c */
+#line 318 "a.y"
{
(yyval.gen) = (yyvsp[(2) - (2)].gen);
}
break;
- case 63:
-/* Line 1778 of yacc.c */
-#line 311 "a.y"
+ case 65:
+
+/* Line 1806 of yacc.c */
+#line 322 "a.y"
{
(yyval.gen) = (yyvsp[(2) - (2)].gen);
}
break;
- case 69:
-/* Line 1778 of yacc.c */
-#line 324 "a.y"
+ case 71:
+
+/* Line 1806 of yacc.c */
+#line 335 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_BRANCH;
@@ -2104,9 +2205,10 @@ yyreduce:
}
break;
- case 70:
-/* Line 1778 of yacc.c */
-#line 330 "a.y"
+ case 72:
+
+/* Line 1806 of yacc.c */
+#line 341 "a.y"
{
(yyval.gen) = nullgen;
if(pass == 2)
@@ -2117,9 +2219,10 @@ yyreduce:
}
break;
- case 71:
-/* Line 1778 of yacc.c */
-#line 339 "a.y"
+ case 73:
+
+/* Line 1806 of yacc.c */
+#line 350 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_BRANCH;
@@ -2128,63 +2231,70 @@ yyreduce:
}
break;
- case 72:
-/* Line 1778 of yacc.c */
-#line 348 "a.y"
+ case 74:
+
+/* Line 1806 of yacc.c */
+#line 359 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(1) - (1)].lval);
}
break;
- case 73:
-/* Line 1778 of yacc.c */
-#line 353 "a.y"
+ case 75:
+
+/* Line 1806 of yacc.c */
+#line 364 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(1) - (1)].lval);
}
break;
- case 74:
-/* Line 1778 of yacc.c */
-#line 358 "a.y"
+ case 76:
+
+/* Line 1806 of yacc.c */
+#line 369 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(1) - (1)].lval);
}
break;
- case 75:
-/* Line 1778 of yacc.c */
-#line 363 "a.y"
+ case 77:
+
+/* Line 1806 of yacc.c */
+#line 374 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(1) - (1)].lval);
}
break;
- case 76:
-/* Line 1778 of yacc.c */
-#line 368 "a.y"
+ case 78:
+
+/* Line 1806 of yacc.c */
+#line 379 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_SP;
}
break;
- case 77:
-/* Line 1778 of yacc.c */
-#line 373 "a.y"
+ case 79:
+
+/* Line 1806 of yacc.c */
+#line 384 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(1) - (1)].lval);
}
break;
- case 78:
-/* Line 1778 of yacc.c */
-#line 380 "a.y"
+ case 80:
+
+/* Line 1806 of yacc.c */
+#line 391 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_CONST;
@@ -2192,9 +2302,10 @@ yyreduce:
}
break;
- case 79:
-/* Line 1778 of yacc.c */
-#line 386 "a.y"
+ case 81:
+
+/* Line 1806 of yacc.c */
+#line 397 "a.y"
{
(yyval.gen) = (yyvsp[(2) - (2)].gen);
(yyval.gen).index = (yyvsp[(2) - (2)].gen).type;
@@ -2207,9 +2318,10 @@ yyreduce:
}
break;
- case 80:
-/* Line 1778 of yacc.c */
-#line 397 "a.y"
+ case 82:
+
+/* Line 1806 of yacc.c */
+#line 408 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_SCONST;
@@ -2217,9 +2329,10 @@ yyreduce:
}
break;
- case 81:
-/* Line 1778 of yacc.c */
-#line 403 "a.y"
+ case 83:
+
+/* Line 1806 of yacc.c */
+#line 414 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_FCONST;
@@ -2227,9 +2340,10 @@ yyreduce:
}
break;
- case 82:
-/* Line 1778 of yacc.c */
-#line 409 "a.y"
+ case 84:
+
+/* Line 1806 of yacc.c */
+#line 420 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_FCONST;
@@ -2237,9 +2351,10 @@ yyreduce:
}
break;
- case 83:
-/* Line 1778 of yacc.c */
-#line 415 "a.y"
+ case 85:
+
+/* Line 1806 of yacc.c */
+#line 426 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_FCONST;
@@ -2247,9 +2362,10 @@ yyreduce:
}
break;
- case 84:
-/* Line 1778 of yacc.c */
-#line 421 "a.y"
+ case 86:
+
+/* Line 1806 of yacc.c */
+#line 432 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_FCONST;
@@ -2257,9 +2373,10 @@ yyreduce:
}
break;
- case 85:
-/* Line 1778 of yacc.c */
-#line 429 "a.y"
+ case 87:
+
+/* Line 1806 of yacc.c */
+#line 440 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_CONST2;
@@ -2268,45 +2385,50 @@ yyreduce:
}
break;
- case 86:
-/* Line 1778 of yacc.c */
-#line 438 "a.y"
+ case 88:
+
+/* Line 1806 of yacc.c */
+#line 449 "a.y"
{
(yyval.con2).v1 = (yyvsp[(1) - (1)].lval);
(yyval.con2).v2 = 0;
}
break;
- case 87:
-/* Line 1778 of yacc.c */
-#line 443 "a.y"
+ case 89:
+
+/* Line 1806 of yacc.c */
+#line 454 "a.y"
{
(yyval.con2).v1 = -(yyvsp[(2) - (2)].lval);
(yyval.con2).v2 = 0;
}
break;
- case 88:
-/* Line 1778 of yacc.c */
-#line 448 "a.y"
+ case 90:
+
+/* Line 1806 of yacc.c */
+#line 459 "a.y"
{
(yyval.con2).v1 = (yyvsp[(1) - (3)].lval);
(yyval.con2).v2 = (yyvsp[(3) - (3)].lval);
}
break;
- case 89:
-/* Line 1778 of yacc.c */
-#line 453 "a.y"
+ case 91:
+
+/* Line 1806 of yacc.c */
+#line 464 "a.y"
{
(yyval.con2).v1 = -(yyvsp[(2) - (4)].lval);
(yyval.con2).v2 = (yyvsp[(4) - (4)].lval);
}
break;
- case 92:
-/* Line 1778 of yacc.c */
-#line 464 "a.y"
+ case 94:
+
+/* Line 1806 of yacc.c */
+#line 475 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+D_NONE;
@@ -2314,9 +2436,10 @@ yyreduce:
}
break;
- case 93:
-/* Line 1778 of yacc.c */
-#line 470 "a.y"
+ case 95:
+
+/* Line 1806 of yacc.c */
+#line 481 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2324,9 +2447,10 @@ yyreduce:
}
break;
- case 94:
-/* Line 1778 of yacc.c */
-#line 476 "a.y"
+ case 96:
+
+/* Line 1806 of yacc.c */
+#line 487 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+D_SP;
@@ -2334,9 +2458,10 @@ yyreduce:
}
break;
- case 95:
-/* Line 1778 of yacc.c */
-#line 482 "a.y"
+ case 97:
+
+/* Line 1806 of yacc.c */
+#line 493 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+D_NONE;
@@ -2347,9 +2472,10 @@ yyreduce:
}
break;
- case 96:
-/* Line 1778 of yacc.c */
-#line 491 "a.y"
+ case 98:
+
+/* Line 1806 of yacc.c */
+#line 502 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+(yyvsp[(3) - (9)].lval);
@@ -2360,27 +2486,30 @@ yyreduce:
}
break;
- case 97:
-/* Line 1778 of yacc.c */
-#line 500 "a.y"
+ case 99:
+
+/* Line 1806 of yacc.c */
+#line 511 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+(yyvsp[(2) - (3)].lval);
}
break;
- case 98:
-/* Line 1778 of yacc.c */
-#line 505 "a.y"
+ case 100:
+
+/* Line 1806 of yacc.c */
+#line 516 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+D_SP;
}
break;
- case 99:
-/* Line 1778 of yacc.c */
-#line 510 "a.y"
+ case 101:
+
+/* Line 1806 of yacc.c */
+#line 521 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2388,9 +2517,10 @@ yyreduce:
}
break;
- case 100:
-/* Line 1778 of yacc.c */
-#line 516 "a.y"
+ case 102:
+
+/* Line 1806 of yacc.c */
+#line 527 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+D_NONE;
@@ -2400,9 +2530,10 @@ yyreduce:
}
break;
- case 101:
-/* Line 1778 of yacc.c */
-#line 524 "a.y"
+ case 103:
+
+/* Line 1806 of yacc.c */
+#line 535 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+(yyvsp[(2) - (8)].lval);
@@ -2412,17 +2543,19 @@ yyreduce:
}
break;
- case 102:
-/* Line 1778 of yacc.c */
-#line 534 "a.y"
+ case 104:
+
+/* Line 1806 of yacc.c */
+#line 545 "a.y"
{
(yyval.gen) = (yyvsp[(1) - (1)].gen);
}
break;
- case 103:
-/* Line 1778 of yacc.c */
-#line 538 "a.y"
+ case 105:
+
+/* Line 1806 of yacc.c */
+#line 549 "a.y"
{
(yyval.gen) = (yyvsp[(1) - (6)].gen);
(yyval.gen).index = (yyvsp[(3) - (6)].lval);
@@ -2431,9 +2564,10 @@ yyreduce:
}
break;
- case 104:
-/* Line 1778 of yacc.c */
-#line 547 "a.y"
+ case 106:
+
+/* Line 1806 of yacc.c */
+#line 558 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(4) - (5)].lval);
@@ -2442,9 +2576,10 @@ yyreduce:
}
break;
- case 105:
-/* Line 1778 of yacc.c */
-#line 554 "a.y"
+ case 107:
+
+/* Line 1806 of yacc.c */
+#line 565 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_STATIC;
@@ -2453,161 +2588,181 @@ yyreduce:
}
break;
- case 106:
-/* Line 1778 of yacc.c */
-#line 562 "a.y"
+ case 108:
+
+/* Line 1806 of yacc.c */
+#line 573 "a.y"
{
(yyval.lval) = 0;
}
break;
- case 107:
-/* Line 1778 of yacc.c */
-#line 566 "a.y"
+ case 109:
+
+/* Line 1806 of yacc.c */
+#line 577 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 108:
-/* Line 1778 of yacc.c */
-#line 570 "a.y"
+ case 110:
+
+/* Line 1806 of yacc.c */
+#line 581 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 110:
-/* Line 1778 of yacc.c */
-#line 577 "a.y"
+ case 112:
+
+/* Line 1806 of yacc.c */
+#line 588 "a.y"
{
(yyval.lval) = D_AUTO;
}
break;
- case 113:
-/* Line 1778 of yacc.c */
-#line 585 "a.y"
+ case 115:
+
+/* Line 1806 of yacc.c */
+#line 596 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
}
break;
- case 114:
-/* Line 1778 of yacc.c */
-#line 589 "a.y"
+ case 116:
+
+/* Line 1806 of yacc.c */
+#line 600 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 115:
-/* Line 1778 of yacc.c */
-#line 593 "a.y"
+ case 117:
+
+/* Line 1806 of yacc.c */
+#line 604 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 116:
-/* Line 1778 of yacc.c */
-#line 597 "a.y"
+ case 118:
+
+/* Line 1806 of yacc.c */
+#line 608 "a.y"
{
(yyval.lval) = ~(yyvsp[(2) - (2)].lval);
}
break;
- case 117:
-/* Line 1778 of yacc.c */
-#line 601 "a.y"
+ case 119:
+
+/* Line 1806 of yacc.c */
+#line 612 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (3)].lval);
}
break;
- case 119:
-/* Line 1778 of yacc.c */
-#line 608 "a.y"
+ case 121:
+
+/* Line 1806 of yacc.c */
+#line 619 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
}
break;
- case 120:
-/* Line 1778 of yacc.c */
-#line 612 "a.y"
+ case 122:
+
+/* Line 1806 of yacc.c */
+#line 623 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
}
break;
- case 121:
-/* Line 1778 of yacc.c */
-#line 616 "a.y"
+ case 123:
+
+/* Line 1806 of yacc.c */
+#line 627 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
}
break;
- case 122:
-/* Line 1778 of yacc.c */
-#line 620 "a.y"
+ case 124:
+
+/* Line 1806 of yacc.c */
+#line 631 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
}
break;
- case 123:
-/* Line 1778 of yacc.c */
-#line 624 "a.y"
+ case 125:
+
+/* Line 1806 of yacc.c */
+#line 635 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
}
break;
- case 124:
-/* Line 1778 of yacc.c */
-#line 628 "a.y"
+ case 126:
+
+/* Line 1806 of yacc.c */
+#line 639 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
}
break;
- case 125:
-/* Line 1778 of yacc.c */
-#line 632 "a.y"
+ case 127:
+
+/* Line 1806 of yacc.c */
+#line 643 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
}
break;
- case 126:
-/* Line 1778 of yacc.c */
-#line 636 "a.y"
+ case 128:
+
+/* Line 1806 of yacc.c */
+#line 647 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
}
break;
- case 127:
-/* Line 1778 of yacc.c */
-#line 640 "a.y"
+ case 129:
+
+/* Line 1806 of yacc.c */
+#line 651 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
}
break;
- case 128:
-/* Line 1778 of yacc.c */
-#line 644 "a.y"
+ case 130:
+
+/* Line 1806 of yacc.c */
+#line 655 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
}
break;
-/* Line 1778 of yacc.c */
-#line 2611 "y.tab.c"
+
+/* Line 1806 of yacc.c */
+#line 2766 "y.tab.c"
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -2770,9 +2925,7 @@ yyerrlab1:
YY_STACK_PRINT (yyss, yyssp);
}
- YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
- YY_IGNORE_MAYBE_UNINITIALIZED_END
/* Shift the error token. */
@@ -2796,7 +2949,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
-#if !defined yyoverflow || YYERROR_VERBOSE
+#if !defined(yyoverflow) || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
@@ -2838,3 +2991,4 @@ yyreturn:
}
+
diff --git a/src/cmd/8a/y.tab.h b/src/cmd/8a/y.tab.h
index 621aba79f..4d7bbe80d 100644
--- a/src/cmd/8a/y.tab.h
+++ b/src/cmd/8a/y.tab.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 2.6.5. */
+/* A Bison parser, made by GNU Bison 2.5. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,15 +30,6 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
-#ifndef YY_YY_Y_TAB_H_INCLUDED
-# define YY_YY_Y_TAB_H_INCLUDED
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
/* Tokens. */
#ifndef YYTOKENTYPE
@@ -61,21 +52,22 @@ extern int yydebug;
LTYPEI = 270,
LTYPEG = 271,
LTYPEXC = 272,
- LCONST = 273,
- LFP = 274,
- LPC = 275,
- LSB = 276,
- LBREG = 277,
- LLREG = 278,
- LSREG = 279,
- LFREG = 280,
- LXREG = 281,
- LFCONST = 282,
- LSCONST = 283,
- LSP = 284,
- LNAME = 285,
- LLAB = 286,
- LVAR = 287
+ LTYPEX = 273,
+ LCONST = 274,
+ LFP = 275,
+ LPC = 276,
+ LSB = 277,
+ LBREG = 278,
+ LLREG = 279,
+ LSREG = 280,
+ LFREG = 281,
+ LXREG = 282,
+ LFCONST = 283,
+ LSCONST = 284,
+ LSP = 285,
+ LNAME = 286,
+ LLAB = 287,
+ LVAR = 288
};
#endif
/* Tokens. */
@@ -94,28 +86,31 @@ extern int yydebug;
#define LTYPEI 270
#define LTYPEG 271
#define LTYPEXC 272
-#define LCONST 273
-#define LFP 274
-#define LPC 275
-#define LSB 276
-#define LBREG 277
-#define LLREG 278
-#define LSREG 279
-#define LFREG 280
-#define LXREG 281
-#define LFCONST 282
-#define LSCONST 283
-#define LSP 284
-#define LNAME 285
-#define LLAB 286
-#define LVAR 287
+#define LTYPEX 273
+#define LCONST 274
+#define LFP 275
+#define LPC 276
+#define LSB 277
+#define LBREG 278
+#define LLREG 279
+#define LSREG 280
+#define LFREG 281
+#define LXREG 282
+#define LFCONST 283
+#define LSCONST 284
+#define LSP 285
+#define LNAME 286
+#define LLAB 287
+#define LVAR 288
+
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
-/* Line 2042 of yacc.c */
+
+/* Line 2068 of yacc.c */
#line 37 "a.y"
Sym *sym;
@@ -130,8 +125,9 @@ typedef union YYSTYPE
Gen2 gen2;
-/* Line 2042 of yacc.c */
-#line 135 "y.tab.h"
+
+/* Line 2068 of yacc.c */
+#line 131 "y.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -140,18 +136,4 @@ typedef union YYSTYPE
extern YYSTYPE yylval;
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-#endif /* !YY_YY_Y_TAB_H_INCLUDED */
diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c
index d331eee1a..1b8ceb0c6 100644
--- a/src/cmd/8c/swt.c
+++ b/src/cmd/8c/swt.c
@@ -324,7 +324,7 @@ outcode(void)
zaddr(&b, &p->from, sf);
zaddr(&b, &p->to, st);
}
- Bflush(&b);
+ Bterm(&b);
close(f);
firstp = P;
lastp = P;
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index 0b2f2b76e..f93be57e5 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -1055,7 +1055,7 @@ bgen(Node *n, int true, int likely, Prog *to)
}
if(is64(nr->type)) {
- if(!nl->addable) {
+ if(!nl->addable || isconst(nl, CTINT)) {
tempname(&n1, nl->type);
cgen(nl, &n1);
nl = &n1;
diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c
index c4c184bb9..79348a42d 100644
--- a/src/cmd/8g/gsubr.c
+++ b/src/cmd/8g/gsubr.c
@@ -1150,6 +1150,7 @@ ismem(Node *n)
case OINDREG:
case ONAME:
case OPARAM:
+ case OCLOSUREVAR:
return 1;
}
return 0;
@@ -2160,11 +2161,11 @@ gins(int as, Node *f, Node *t)
// Generate an instruction referencing *n
// to force segv on nil pointer dereference.
void
-checkref(Node *n)
+checkref(Node *n, int force)
{
Node m;
- if(n->type->type->width < unmappedzero)
+ if(!force && isptr[n->type->etype] && n->type->type->width < unmappedzero)
return;
regalloc(&m, types[TUINTPTR], n);
@@ -2201,8 +2202,6 @@ checkoffset(Addr *a, int canemitcode)
void
naddr(Node *n, Addr *a, int canemitcode)
{
- Prog *p;
-
a->scale = 0;
a->index = D_NONE;
a->type = D_NONE;
@@ -2239,13 +2238,8 @@ naddr(Node *n, Addr *a, int canemitcode)
break;
case OCLOSUREVAR:
- if(!canemitcode)
- fatal("naddr OCLOSUREVAR cannot emit code");
- p = gins(AMOVL, N, N);
- p->from.type = D_DX+D_INDIR;
- p->from.offset = n->xoffset;
- p->to.type = D_BX;
- a->type = D_BX;
+ a->type = D_DX+D_INDIR;
+ a->offset = n->xoffset;
a->sym = S;
break;
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h
index 386889956..93d44eb51 100644
--- a/src/cmd/8l/8.out.h
+++ b/src/cmd/8l/8.out.h
@@ -153,6 +153,7 @@ enum as
AMOVB,
AMOVL,
AMOVW,
+ AMOVQ,
AMOVBLSX,
AMOVBLZX,
AMOVBWSX,
@@ -397,6 +398,7 @@ enum as
ACMPXCHGW,
ACMPXCHG8B,
+ ACPUID,
ARDTSC,
AXADDB,
@@ -531,6 +533,7 @@ enum as
AORPD,
AORPS,
APADDQ,
+ APAND,
APMAXSW,
APMAXUB,
APMINSW,
@@ -566,7 +569,12 @@ enum as
AUNPCKLPS,
AXORPD,
AXORPS,
-
+
+ /* SSE 3+ */
+ AAESENC,
+ APINSRD,
+ APSHUFB,
+
AUSEFIELD,
ALOCALS,
ATYPE,
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index a00174c36..bfeb13839 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -128,7 +128,7 @@ adddynrel(Sym *s, Reloc *r)
// Handle relocations found in ELF object files.
case 256 + R_386_PC32:
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ->name);
if(targ->type == 0 || targ->type == SXREF)
diag("unknown symbol %s in pcrel", targ->name);
@@ -139,7 +139,7 @@ adddynrel(Sym *s, Reloc *r)
case 256 + R_386_PLT32:
r->type = D_PCREL;
r->add += 4;
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add += targ->plt;
@@ -147,7 +147,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_386_GOT32:
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
// have symbol
// turn MOVL of GOT entry into LEAL of symbol itself
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
@@ -175,19 +175,19 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_386_32:
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected R_386_32 relocation for dynamic symbol %s", targ->name);
r->type = D_ADDR;
return;
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 0:
r->type = D_ADDR;
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected reloc for dynamic symbol %s", targ->name);
return;
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 1:
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = targ->plt;
@@ -198,7 +198,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 512 + MACHO_FAKE_GOTPCREL:
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
// have symbol
// turn MOVL of GOT entry into LEAL of symbol itself
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
@@ -217,7 +217,7 @@ adddynrel(Sym *s, Reloc *r)
}
// Handle references to ELF symbols from our own object files.
- if(targ->dynimpname == nil || targ->dynexport)
+ if(targ->type != SDYNIMPORT)
return;
switch(r->type) {
@@ -270,12 +270,13 @@ adddynrel(Sym *s, Reloc *r)
}
int
-elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+elfreloc1(Reloc *r, vlong sectoff)
{
- USED(add); // written to obj file by ../ld/data.c's reloc
+ int32 elfsym;
- LPUT(off);
+ LPUT(sectoff);
+ elfsym = r->xsym->elfsym;
switch(r->type) {
default:
return -1;
@@ -298,6 +299,78 @@ elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
return 0;
}
+int
+machoreloc1(Reloc *r, vlong sectoff)
+{
+ uint32 v;
+ Sym *rs;
+
+ rs = r->xsym;
+
+ if(rs->type == SHOSTOBJ) {
+ if(rs->dynid < 0) {
+ diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type);
+ return -1;
+ }
+ v = rs->dynid;
+ v |= 1<<27; // external relocation
+ } else {
+ v = rs->sect->extnum;
+ if(v == 0) {
+ diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type);
+ return -1;
+ }
+ }
+
+ switch(r->type) {
+ default:
+ return -1;
+ case D_ADDR:
+ v |= MACHO_GENERIC_RELOC_VANILLA<<28;
+ break;
+ case D_PCREL:
+ v |= 1<<24; // pc-relative bit
+ v |= MACHO_GENERIC_RELOC_VANILLA<<28;
+ break;
+ }
+
+ switch(r->siz) {
+ default:
+ return -1;
+ case 1:
+ v |= 0<<25;
+ break;
+ case 2:
+ v |= 1<<25;
+ break;
+ case 4:
+ v |= 2<<25;
+ break;
+ case 8:
+ v |= 3<<25;
+ break;
+ }
+
+ LPUT(sectoff);
+ LPUT(v);
+ return 0;
+}
+
+int
+archreloc(Reloc *r, Sym *s, vlong *val)
+{
+ USED(s);
+ switch(r->type) {
+ case D_CONST:
+ *val = r->add;
+ return 0;
+ case D_GOTOFF:
+ *val = symaddr(r->sym) + r->add - symaddr(lookup(".got", 0));
+ return 0;
+ }
+ return -1;
+}
+
void
elfsetupplt(void)
{
@@ -326,21 +399,6 @@ elfsetupplt(void)
}
}
-int
-archreloc(Reloc *r, Sym *s, vlong *val)
-{
- USED(s);
- switch(r->type) {
- case D_CONST:
- *val = r->add;
- return 0;
- case D_GOTOFF:
- *val = symaddr(r->sym) + r->add - symaddr(lookup(".got", 0));
- return 0;
- }
- return -1;
-}
-
static void
addpltsym(Sym *s)
{
@@ -428,26 +486,20 @@ addgotsym(Sym *s)
void
adddynsym(Sym *s)
{
- Sym *d, *str;
+ Sym *d;
int t;
char *name;
- vlong off;
if(s->dynid >= 0)
return;
- if(s->dynimpname == nil)
- diag("adddynsym: no dynamic name for %s", s->name);
-
if(iself) {
s->dynid = nelfsym++;
d = lookup(".dynsym", 0);
/* name */
- name = s->dynimpname;
- if(name == nil)
- name = s->name;
+ name = s->extname;
adduint32(d, addstring(lookup(".dynstr", 0), name));
/* value */
@@ -461,7 +513,7 @@ adddynsym(Sym *s)
/* type */
t = STB_GLOBAL << 4;
- if(s->dynexport && (s->type&SMASK) == STEXT)
+ if(s->cgoexport && (s->type&SMASK) == STEXT)
t |= STT_FUNC;
else
t |= STT_OBJECT;
@@ -469,7 +521,7 @@ adddynsym(Sym *s)
adduint8(d, 0);
/* shndx */
- if(!s->dynexport && s->dynimpname != nil)
+ if(s->type == SDYNIMPORT)
adduint16(d, SHN_UNDEF);
else {
switch(s->type) {
@@ -490,57 +542,10 @@ adddynsym(Sym *s)
adduint16(d, t);
}
} else if(HEADTYPE == Hdarwin) {
- // Mach-O symbol nlist32
- d = lookup(".dynsym", 0);
- name = s->dynimpname;
- if(name == nil)
- name = s->name;
- if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps
- symgrow(d, ndynexp*12);
- }
- if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp()
- s->dynid = -s->dynid-100;
- off = s->dynid*12;
- } else {
- off = d->size;
- s->dynid = off/12;
- }
- // darwin still puts _ prefixes on all C symbols
- str = lookup(".dynstr", 0);
- setuint32(d, off, str->size);
- off += 4;
- adduint8(str, '_');
- addstring(str, name);
- if(s->type == SDYNIMPORT) {
- setuint8(d, off, 0x01); // type - N_EXT - external symbol
- off++;
- setuint8(d, off, 0); // section
- off++;
- } else {
- setuint8(d, off, 0x0f);
- off++;
- switch(s->type) {
- default:
- case STEXT:
- setuint8(d, off, 1);
- break;
- case SDATA:
- setuint8(d, off, 2);
- break;
- case SBSS:
- setuint8(d, off, 4);
- break;
- }
- off++;
- }
- setuint16(d, off, 0); // desc
- off += 2;
- if(s->type == SDYNIMPORT)
- setuint32(d, off, 0); // value
- else
- setaddr(d, off, s);
- off += 4;
- } else if(HEADTYPE != Hwindows) {
+ diag("adddynsym: missed symbol %s (%s)", s->name, s->extname);
+ } else if(HEADTYPE == Hwindows) {
+ // already taken care of
+ } else {
diag("adddynsym: unsupported binary format");
}
}
@@ -666,7 +671,7 @@ asmb(void)
Bprint(&bso, "%5.2f dwarf\n", cputime());
dwarfemitdebugsections();
- if(isobj)
+ if(linkmode == LinkExternal)
elfemitreloc();
}
break;
@@ -688,6 +693,10 @@ asmb(void)
Bprint(&bso, "%5.2f dwarf\n", cputime());
dwarfemitdebugsections();
break;
+ case Hdarwin:
+ if(linkmode == LinkExternal)
+ machoemitreloc();
+ break;
}
}
if(debug['v'])
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index f88f058e3..980a7f830 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -42,6 +42,7 @@ enum
thechar = '8',
PtrSize = 4,
IntSize = 4,
+ MaxAlign = 32, // max data alignment
FuncAlign = 16
};
@@ -83,9 +84,12 @@ struct Reloc
{
int32 off;
uchar siz;
+ uchar done;
int32 type;
int32 add;
+ int32 xadd;
Sym* sym;
+ Sym* xsym;
};
struct Prog
@@ -122,11 +126,12 @@ struct Auto
struct Sym
{
char* name;
+ char* extname; // name used in external object files
short type;
short version;
uchar dupok;
uchar reachable;
- uchar dynexport;
+ uchar cgoexport;
uchar special;
uchar stkcheck;
uchar hide;
@@ -149,7 +154,6 @@ struct Sym
Sym* reachparent;
Sym* queue;
char* file;
- char* dynimpname;
char* dynimplib;
char* dynimpvers;
struct Section* sect;
@@ -172,7 +176,7 @@ struct Optab
short as;
uchar* ytab;
uchar prefix;
- uchar op[10];
+ uchar op[12];
};
enum
@@ -217,6 +221,7 @@ enum
Zxxx = 0,
Zlit,
+ Zlitm_r,
Z_rp,
Zbr,
Zcall,
@@ -233,6 +238,7 @@ enum
Zloop,
Zm_o,
Zm_r,
+ Zm2_r,
Zm_r_xm,
Zm_r_i_xm,
Zaut_r,
@@ -249,6 +255,7 @@ enum
Zib_rr,
Zil_rr,
Zclr,
+ Zibm_r, /* mmx1,mmx2/mem64,imm8 */
Zbyte,
Zmov,
Zmax,
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index dcb8390b9..306e288a3 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -90,6 +90,7 @@ main(int argc, char *argv[])
INITRND = -1;
INITENTRY = 0;
LIBINITENTRY = 0;
+ linkmode = LinkInternal; // TODO: LinkAuto once everything works.
nuxiinit();
flagcount("1", "use alternate profiling code", &debug['1']);
@@ -114,7 +115,7 @@ main(int argc, char *argv[])
flagcount("d", "disable dynamic executable", &debug['d']);
flagcount("f", "ignore version mismatch", &debug['f']);
flagcount("g", "disable go package data checks", &debug['g']);
- flagcount("hostobj", "generate host object file", &isobj);
+ flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
flagstr("k", "sym: set field tracking symbol", &tracksym);
flagstr("o", "outfile: set output file", &outfile);
flagcount("p", "insert profiling code", &debug['p']);
@@ -122,9 +123,11 @@ main(int argc, char *argv[])
flagcount("race", "enable race detector", &flag_race);
flagcount("s", "disable symbol table", &debug['s']);
flagcount("n", "dump symbol table", &debug['n']);
+ flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
flagcount("u", "reject unsafe packages", &debug['u']);
flagcount("v", "print link trace", &debug['v']);
flagcount("w", "disable DWARF generation", &debug['w']);
+ // TODO: link mode flag
flagparse(&argc, &argv, usage);
@@ -136,13 +139,19 @@ main(int argc, char *argv[])
if(HEADTYPE == -1)
HEADTYPE = headtype(goos);
- if(isobj) {
- switch(HEADTYPE) {
- default:
- sysfatal("cannot use -hostobj with -H %s", headstr(HEADTYPE));
- case Hlinux:
- break;
- }
+ switch(HEADTYPE) {
+ default:
+ if(linkmode == LinkAuto)
+ linkmode = LinkInternal;
+ if(linkmode == LinkExternal)
+ sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
+ break;
+ case Hdarwin:
+ case Hfreebsd:
+ case Hlinux:
+ case Hnetbsd:
+ case Hopenbsd:
+ break;
}
if(outfile == nil) {
@@ -308,6 +317,8 @@ main(int argc, char *argv[])
reloc();
asmb();
undef();
+ hostlink();
+
if(debug['v']) {
Bprint(&bso, "%5.2f cpu time\n", cputime());
Bprint(&bso, "%d symbols\n", nsymbol);
@@ -431,7 +442,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
ntext = 0;
eof = Boffset(f) + len;
src[0] = 0;
-
+ pn = estrdup(pn); // we keep it in Sym* references
newloop:
memset(h, 0, sizeof(h));
diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c
index 79d7b39f0..a6ebf063e 100644
--- a/src/cmd/8l/optab.c
+++ b/src/cmd/8l/optab.c
@@ -150,9 +150,16 @@ uchar ymovl[] =
// Yi0, Yml, Zibo_m, 2, // shorter but slower AND $0,dst
Yi32, Yrl, Zil_rp, 1,
Yi32, Yml, Zilo_m, 2,
+ Yml, Yxr, Zm_r_xm, 2, // XMM MOVD (32 bit)
+ Yxr, Yml, Zr_m_xm, 2, // XMM MOVD (32 bit)
Yiauto, Yrl, Zaut_r, 2,
0
};
+uchar ymovq[] =
+{
+ Yml, Yxr, Zm_r_xm, 2,
+ 0
+};
uchar ym_rl[] =
{
Ym, Yrl, Zm_r, 1,
@@ -435,6 +442,21 @@ uchar yprefetch[] =
Ym, Ynone, Zm_o, 2,
0,
};
+uchar yaes[] =
+{
+ Yxm, Yxr, Zlitm_r, 2,
+ 0
+};
+uchar yinsrd[] =
+{
+ Yml, Yxr, Zibm_r, 2,
+ 0
+};
+uchar ymshufb[] =
+{
+ Yxm, Yxr, Zm2_r, 2,
+ 0
+};
Optab optab[] =
/* as, ytab, andproto, opcode */
@@ -552,8 +574,9 @@ Optab optab[] =
{ ALSLL, yml_rl, Pm, 0x03 },
{ ALSLW, yml_rl, Pq, 0x03 },
{ AMOVB, ymovb, Pb, 0x88,0x8a,0xb0,0xc6,(00) },
- { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00) },
+ { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),Pe,0x6e,Pe,0x7e },
{ AMOVW, ymovl, Pe, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00) },
+ { AMOVQ, ymovq, Pf3, 0x7e },
{ AMOVBLSX, ymb_rl, Pm, 0xbe },
{ AMOVBLZX, ymb_rl, Pm, 0xb6 },
{ AMOVBWSX, ymb_rl, Pq, 0xbe },
@@ -793,6 +816,7 @@ Optab optab[] =
{ ACMPXCHGW, yrl_ml, Pm, 0xb1 },
{ ACMPXCHG8B, yscond, Pm, 0xc7,(01) },
+ { ACPUID, ynone, Pm, 0xa2 },
{ ARDTSC, ynone, Pm, 0x31 },
{ AXADDB, yrb_mb, Pb, 0x0f,0xc0 },
@@ -925,6 +949,7 @@ Optab optab[] =
{ AORPD, yxm, Pq, 0x56 },
{ AORPS, yxm, Pm, 0x56 },
{ APADDQ, yxm, Pe, 0xd4 },
+ { APAND, yxm, Pe, 0xdb },
{ APMAXSW, yxm, Pe, 0xee },
{ APMAXUB, yxm, Pe, 0xde },
{ APMINSW, yxm, Pe, 0xea },
@@ -961,6 +986,10 @@ Optab optab[] =
{ AXORPD, yxm, Pe, 0x57 },
{ AXORPS, yxm, Pm, 0x57 },
+ { AAESENC, yaes, Pq, 0x38,0xdc,(0) },
+ { APINSRD, yinsrd, Pq, 0x3a, 0x22, (00) },
+ { APSHUFB, ymshufb,Pq, 0x38, 0x00 },
+
{ AUSEFIELD, ynop, Px, 0,0 },
{ ALOCALS },
{ ATYPE },
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index b828d8645..0678fa8f2 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -1003,11 +1003,23 @@ found:
*andptr++ = op;
break;
+ case Zlitm_r:
+ for(; op = o->op[z]; z++)
+ *andptr++ = op;
+ asmand(&p->from, reg[p->to.type]);
+ break;
+
case Zm_r:
*andptr++ = op;
asmand(&p->from, reg[p->to.type]);
break;
+ case Zm2_r:
+ *andptr++ = op;
+ *andptr++ = o->op[z+1];
+ asmand(&p->from, reg[p->to.type]);
+ break;
+
case Zm_r_xm:
mediaop(o, op, t[3], z);
asmand(&p->from, reg[p->to.type]);
@@ -1019,6 +1031,13 @@ found:
*andptr++ = p->to.offset;
break;
+ case Zibm_r:
+ while ((op = o->op[z++]) != 0)
+ *andptr++ = op;
+ asmand(&p->from, reg[p->to.type]);
+ *andptr++ = p->to.offset;
+ break;
+
case Zaut_r:
*andptr++ = 0x8d; /* leal */
if(p->from.type != D_ADDR)
diff --git a/src/cmd/addr2line/main.c b/src/cmd/addr2line/main.c
index 6b2fe5dfe..9faadc27b 100644
--- a/src/cmd/addr2line/main.c
+++ b/src/cmd/addr2line/main.c
@@ -12,12 +12,18 @@
#include <mach.h>
void
+printusage(int fd)
+{
+ fprint(fd, "usage: addr2line binary\n");
+ fprint(fd, "reads addresses from standard input and writes two lines for each:\n");
+ fprint(fd, "\tfunction name\n");
+ fprint(fd, "\tfile:line\n");
+}
+
+void
usage(void)
{
- fprint(2, "usage: addr2line binary\n");
- fprint(2, "reads addresses from standard input and writes two lines for each:\n");
- fprint(2, "\tfunction name\n");
- fprint(2, "\tfile:line\n");
+ printusage(2);
exits("usage");
}
@@ -32,6 +38,11 @@ main(int argc, char **argv)
Biobuf bin, bout;
char file[1024];
+ if(argc > 1 && strcmp(argv[1], "--help") == 0) {
+ printusage(1);
+ exits(0);
+ }
+
ARGBEGIN{
default:
usage();
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index 0d76b0cdb..d5e66428b 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -138,9 +138,7 @@ func main() {
}
for _, pkg := range pkgs {
- if strings.HasPrefix(pkg, "cmd/") ||
- strings.HasPrefix(pkg, "exp/") ||
- strings.HasPrefix(pkg, "old/") {
+ if strings.HasPrefix(pkg, "cmd/") {
continue
}
if fi, err := os.Stat(filepath.Join(w.root, pkg)); err != nil || !fi.IsDir() {
@@ -725,7 +723,6 @@ func (w *Walker) varValueType(vi interface{}) (string, error) {
default:
return "", fmt.Errorf("unknown const value type %T", vi)
}
- panic("unreachable")
}
// resolveName finds a top-level node named name and returns the node
diff --git a/src/cmd/cc/dpchk.c b/src/cmd/cc/dpchk.c
index 2f038f520..34163ff92 100644
--- a/src/cmd/cc/dpchk.c
+++ b/src/cmd/cc/dpchk.c
@@ -692,22 +692,24 @@ pragcgo(char *verb)
goto out;
}
- if(strcmp(verb, "cgo_export") == 0 || strcmp(verb, "dynexport") == 0) {
+ if(strcmp(verb, "dynexport") == 0)
+ verb = "cgo_export_dynamic";
+ if(strcmp(verb, "cgo_export_static") == 0 || strcmp(verb, "cgo_export_dynamic") == 0) {
local = getimpsym();
if(local == nil)
goto err2;
if(!more()) {
- fmtprint(&pragcgobuf, "cgo_export %q\n", local->name);
+ fmtprint(&pragcgobuf, "%s %q\n", verb, local->name);
goto out;
}
remote = getimpsym();
if(remote == nil)
goto err2;
- fmtprint(&pragcgobuf, "cgo_export %q %q\n", local->name, remote->name);
+ fmtprint(&pragcgobuf, "%s %q %q\n", verb, local->name, remote->name);
goto out;
err2:
- yyerror("usage: #pragma cgo_export local [remote]");
+ yyerror("usage: #pragma %s local [remote]", verb);
goto out;
}
@@ -749,6 +751,18 @@ pragcgo(char *verb)
goto out;
}
+ if(strcmp(verb, "cgo_ldflag") == 0) {
+ p = getquoted();
+ if(p == nil)
+ goto err5;
+ fmtprint(&pragcgobuf, "cgo_ldflag %q\n", p);
+ goto out;
+
+ err5:
+ yyerror("usage: #pragma cgo_ldflag \"arg\"");
+ goto out;
+ }
+
out:
while(getnsc() != '\n')
;
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index 955b7c495..efbeae958 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -70,7 +70,7 @@ assignment context to retrieve both the return value (if any) and the
C errno variable as an error (use _ to skip the result value if the
function returns void). For example:
- n, err := C.atoi("abc")
+ n, err := C.sqrt(-1)
_, err := C.voidFunc()
In C, a function argument written as a fixed size array
@@ -484,16 +484,16 @@ The directives are:
Example:
#pragma cgo_dynamic_linker "/lib/ld-linux.so.2"
-#pragma cgo_export <local> <remote>
+#pragma cgo_export_dynamic <local> <remote>
- In both internal and external linking modes, put the Go symbol
+ In internal linking mode, put the Go symbol
named <local> into the program's exported symbol table as
<remote>, so that C code can refer to it by that name. This
mechanism makes it possible for C code to call back into Go or
to share Go's data.
For compatibility with current versions of SWIG,
- #pragma dynexport is an alias for #pragma cgo_export.
+ #pragma dynexport is an alias for #pragma cgo_export_dynamic.
#pragma cgo_import_static <local>
@@ -505,6 +505,14 @@ The directives are:
Example:
#pragma cgo_import_static puts_wrapper
+#pragma cgo_export_static <local> <remote>
+
+ In external linking mode, put the Go symbol
+ named <local> into the program's exported symbol table as
+ <remote>, so that C code can refer to it by that name. This
+ mechanism makes it possible for C code to call back into Go or
+ to share Go's data.
+
#pragma cgo_ldflag "<arg>"
In external linking mode, invoke the host linker (usually gcc)
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index 4b0a521a8..585f01477 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -139,11 +139,7 @@ NextLine:
// 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, " ")
- }
+ p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
if flag == "CFLAGS" {
// We'll also need these when preprocessing for dwarf information.
p.GccOptions = append(p.GccOptions, args...)
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 7adc795de..ca370ef3f 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -33,7 +33,7 @@ type Package struct {
PtrSize int64
IntSize int64
GccOptions []string
- CgoFlags map[string]string // #cgo flags (CFLAGS, LDFLAGS)
+ CgoFlags map[string][]string // #cgo flags (CFLAGS, LDFLAGS)
Written map[string]bool
Name map[string]*Name // accumulated Name from Files
ExpFunc []*ExpFunc // accumulated ExpFunc from Files
@@ -312,7 +312,7 @@ func newPackage(args []string) *Package {
PtrSize: ptrSize,
IntSize: intSize,
GccOptions: gccOptions,
- CgoFlags: make(map[string]string),
+ CgoFlags: make(map[string][]string),
Written: make(map[string]bool),
}
return p
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index a126cf17f..ee1d89142 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -31,7 +31,12 @@ func (p *Package) writeDefs() {
fflg := creat(*objDir + "_cgo_flags")
for k, v := range p.CgoFlags {
- fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, v)
+ fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
+ if k == "LDFLAGS" {
+ for _, arg := range v {
+ fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg)
+ }
+ }
}
fflg.Close()
@@ -100,6 +105,7 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fm, "extern char %s[];\n", n.C)
fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
+ fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C)
fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
cVars[n.C] = true
@@ -651,8 +657,9 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
if fn.Recv != nil {
goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
}
- fmt.Fprintf(fc, "#pragma cgo_export %s\n", goname)
+ fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname)
fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
+ fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
fmt.Fprintf(fc, "void\n")
fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index dda45ca62..fd6a329c4 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -313,7 +313,6 @@ static char *unreleased[] = {
"src/cmd/cov",
"src/cmd/prof",
"src/pkg/old",
- "src/pkg/exp",
};
// setup sets up the tree for the initial build.
@@ -795,6 +794,9 @@ install(char *dir)
bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0);
copy(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0);
+ p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch);
+ if(isfile(p))
+ copy(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
copy(bpathf(&b, "%s/os_GOOS.h", workdir),
bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0);
copy(bpathf(&b, "%s/signals_GOOS.h", workdir),
@@ -940,6 +942,8 @@ install(char *dir)
}
vadd(&compile, "-I");
vadd(&compile, workdir);
+ vadd(&compile, "-I");
+ vadd(&compile, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
vadd(&compile, "-D");
vadd(&compile, bprintf(&b, "GOOS_%s", goos));
vadd(&compile, "-D");
@@ -1045,7 +1049,16 @@ out:
static bool
matchfield(char *f)
{
- return streq(f, goos) || streq(f, goarch) || streq(f, "cmd_go_bootstrap");
+ char *p;
+ bool res;
+
+ p = xstrrchr(f, ',');
+ if(p == nil)
+ return streq(f, goos) || streq(f, goarch) || streq(f, "cmd_go_bootstrap") || streq(f, "go1.1");
+ *p = 0;
+ res = matchfield(f) && matchfield(p+1);
+ *p = ',';
+ return res;
}
// shouldbuild reports whether we should build this file.
@@ -1071,7 +1084,8 @@ shouldbuild(char *file, char *dir)
name = lastelem(file);
if(streq(name, "goos.c") || streq(name, "flag.c"))
return 1;
- return 0;
+ if(!contains(name, "plan9"))
+ return 0;
}
if(streq(dir, "libbio"))
return 0;
@@ -1574,7 +1588,7 @@ cmdclean(int argc, char **argv)
void
cmdbanner(int argc, char **argv)
{
- char *pathsep;
+ char *pathsep, *pid, *ns;
Buf b, b1, search, path;
ARGBEGIN{
@@ -1598,15 +1612,28 @@ cmdbanner(int argc, char **argv)
xprintf("Installed Go for %s/%s in %s\n", goos, goarch, goroot);
xprintf("Installed commands in %s\n", gobin);
- // Check that gobin appears in $PATH.
- xgetenv(&b, "PATH");
- pathsep = ":";
- if(streq(gohostos, "windows"))
- pathsep = ";";
- bprintf(&b1, "%s%s%s", pathsep, bstr(&b), pathsep);
- bprintf(&search, "%s%s%s", pathsep, gobin, pathsep);
- if(xstrstr(bstr(&b1), bstr(&search)) == nil)
- xprintf("*** You need to add %s to your PATH.\n", gobin);
+ if(streq(gohostos, "plan9")) {
+ // Check that gobin is bound before /bin.
+ readfile(&b, "#c/pid");
+ bsubst(&b, " ", "");
+ pid = btake(&b);
+ bprintf(&b, "/proc/%s/ns", pid);
+ ns = btake(&b);
+ readfile(&b, ns);
+ bprintf(&search, "bind -b %s /bin\n", gobin);
+ if(xstrstr(bstr(&b), bstr(&search)) == nil)
+ xprintf("*** You need to bind %s before /bin.\n", gobin);
+ } else {
+ // Check that gobin appears in $PATH.
+ xgetenv(&b, "PATH");
+ pathsep = ":";
+ if(streq(gohostos, "windows"))
+ pathsep = ";";
+ bprintf(&b1, "%s%s%s", pathsep, bstr(&b), pathsep);
+ bprintf(&search, "%s%s%s", pathsep, gobin, pathsep);
+ if(xstrstr(bstr(&b1), bstr(&search)) == nil)
+ xprintf("*** You need to add %s to your PATH.\n", gobin);
+ }
if(streq(gohostos, "darwin")) {
if(isfile(bpathf(&path, "%s/cov", tooldir)))
diff --git a/src/cmd/dist/windows.c b/src/cmd/dist/windows.c
index 7bcda4508..ba23a7ae8 100644
--- a/src/cmd/dist/windows.c
+++ b/src/cmd/dist/windows.c
@@ -271,6 +271,8 @@ static void bgwait1(void);
static void
genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
{
+ // Another copy of this logic is in ../../lib9/run_windows.c.
+ // If there's a bug here, fix the logic there too.
int i, j, nslash;
Buf cmd;
char *q;
diff --git a/src/cmd/fix/netipv6zone.go b/src/cmd/fix/netipv6zone.go
index 587b9ffec..fe973a211 100644
--- a/src/cmd/fix/netipv6zone.go
+++ b/src/cmd/fix/netipv6zone.go
@@ -14,7 +14,7 @@ var netipv6zoneFix = fix{
"netipv6zone",
"2012-11-26",
netipv6zone,
- `Adapt element key to IPNet, IPAddr, UDPAddr or TCPAddr composite literals.
+ `Adapt element key to IPAddr, UDPAddr or TCPAddr composite literals.
https://codereview.appspot.com/6849045/
`,
@@ -39,7 +39,7 @@ func netipv6zone(f *ast.File) bool {
return
}
switch ss := se.Sel.String(); ss {
- case "IPNet", "IPAddr", "UDPAddr", "TCPAddr":
+ case "IPAddr", "UDPAddr", "TCPAddr":
for i, e := range cl.Elts {
if _, ok := e.(*ast.KeyValueExpr); ok {
break
@@ -51,11 +51,8 @@ func netipv6zone(f *ast.File) bool {
Value: e,
}
case 1:
- if ss == "IPNet" {
- cl.Elts[i] = &ast.KeyValueExpr{
- Key: ast.NewIdent("Mask"),
- Value: e,
- }
+ if e.(*ast.BasicLit).Value == "0" {
+ cl.Elts = append(cl.Elts[:i], cl.Elts[i+1:]...)
} else {
cl.Elts[i] = &ast.KeyValueExpr{
Key: ast.NewIdent("Port"),
diff --git a/src/cmd/fix/netipv6zone_test.go b/src/cmd/fix/netipv6zone_test.go
index 229daa386..0fab00531 100644
--- a/src/cmd/fix/netipv6zone_test.go
+++ b/src/cmd/fix/netipv6zone_test.go
@@ -15,36 +15,24 @@ var netipv6zoneTests = []testCase{
import "net"
-var a = []struct {
- *net.IPNet
-}{
- &net.IPNet{net.ParseIP("2001:DB8::"), net.IPMask(net.ParseIP("ffff:ffff:ffff::"))},
-}
-
func f() net.Addr {
- b := net.IPNet{net.IPv4(127, 0, 0, 1), net.IPv4Mask(255, 0, 0, 0)}
- c := &net.IPAddr{ip1}
+ a := &net.IPAddr{ip1}
sub(&net.UDPAddr{ip2, 12345})
- d := &net.TCPAddr{IP: ip3, Port: 54321}
- return &net.TCPAddr{ip4}, nil
+ c := &net.TCPAddr{IP: ip3, Port: 54321}
+ d := &net.TCPAddr{ip4, 0}
+ return &net.TCPAddr{ip5}, nil
}
`,
Out: `package main
import "net"
-var a = []struct {
- *net.IPNet
-}{
- &net.IPNet{IP: net.ParseIP("2001:DB8::"), Mask: net.IPMask(net.ParseIP("ffff:ffff:ffff::"))},
-}
-
func f() net.Addr {
- b := net.IPNet{IP: net.IPv4(127, 0, 0, 1), Mask: net.IPv4Mask(255, 0, 0, 0)}
- c := &net.IPAddr{IP: ip1}
+ a := &net.IPAddr{IP: ip1}
sub(&net.UDPAddr{IP: ip2, Port: 12345})
- d := &net.TCPAddr{IP: ip3, Port: 54321}
- return &net.TCPAddr{IP: ip4}, nil
+ c := &net.TCPAddr{IP: ip3, Port: 54321}
+ d := &net.TCPAddr{IP: ip4}
+ return &net.TCPAddr{IP: ip5}, nil
}
`,
},
diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c
index 7de448d1e..f1d0931d4 100644
--- a/src/cmd/gc/builtin.c
+++ b/src/cmd/gc/builtin.c
@@ -63,7 +63,13 @@ char *runtimeimport =
"func @\"\".equal (@\"\".typ·2 *byte, @\"\".x1·3 any, @\"\".x2·4 any) (@\"\".ret·1 bool)\n"
"func @\"\".makemap (@\"\".mapType·2 *byte, @\"\".hint·3 int64) (@\"\".hmap·1 map[any]any)\n"
"func @\"\".mapaccess1 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 any)\n"
+ "func @\"\".mapaccess1_fast32 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
+ "func @\"\".mapaccess1_fast64 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
+ "func @\"\".mapaccess1_faststr (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
"func @\"\".mapaccess2 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 any, @\"\".pres·2 bool)\n"
+ "func @\"\".mapaccess2_fast32 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
+ "func @\"\".mapaccess2_fast64 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
+ "func @\"\".mapaccess2_faststr (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
"func @\"\".mapassign1 (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 any, @\"\".val·4 any)\n"
"func @\"\".mapiterinit (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".hiter·3 *any)\n"
"func @\"\".mapdelete (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 any)\n"
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
index 4e029ef83..aca30dc1c 100644
--- a/src/cmd/gc/closure.c
+++ b/src/cmd/gc/closure.c
@@ -60,6 +60,7 @@ closurebody(NodeList *body)
func = curfn;
func->nbody = body;
+ func->endlineno = lineno;
funcbody(func);
// closure-specific variables are hanging off the
@@ -154,6 +155,7 @@ makeclosure(Node *func, int nowrap)
declare(xfunc->nname, PFUNC);
xfunc->nname->funcdepth = func->funcdepth;
xfunc->funcdepth = func->funcdepth;
+ xfunc->endlineno = func->endlineno;
// declare variables holding addresses taken from closure
// and initialize in entry prologue.
@@ -255,26 +257,167 @@ walkclosure(Node *func, NodeList **init)
return clos;
}
-// 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.
+static Node *makepartialcall(Node*, Type*, Node*);
+
void
-walkcallclosure(Node *n, NodeList **init)
+typecheckpartialcall(Node *fn, Node *sym)
+{
+ switch(fn->op) {
+ case ODOTINTER:
+ case ODOTMETH:
+ break;
+ default:
+ fatal("invalid typecheckpartialcall");
+ }
+
+ // Create top-level function.
+ fn->nname = makepartialcall(fn, fn->type, sym);
+ fn->right = sym;
+ fn->op = OCALLPART;
+ fn->type = fn->nname->type;
+}
+
+static Node*
+makepartialcall(Node *fn, Type *t0, Node *meth)
{
- USED(init);
- if (n->op != OCALLFUNC || n->left->op != OCLOSURE) {
- dump("walkcallclosure", n);
- fatal("abuse of walkcallclosure");
+ Node *ptr, *n, *call, *xtype, *xfunc, *cv;
+ Type *rcvrtype, *basetype, *t;
+ NodeList *body, *l, *callargs, *retargs;
+ char *p;
+ Sym *sym;
+ int i;
+
+ // TODO: names are not right
+ rcvrtype = fn->left->type;
+ if(exportname(meth->sym->name))
+ p = smprint("%-hT.%s·fm", rcvrtype, meth->sym->name);
+ else
+ p = smprint("%-hT.(%-S)·fm", rcvrtype, meth->sym);
+ basetype = rcvrtype;
+ if(isptr[rcvrtype->etype])
+ basetype = basetype->type;
+ if(basetype->sym == S)
+ fatal("missing base type for %T", rcvrtype);
+
+ sym = pkglookup(p, basetype->sym->pkg);
+ free(p);
+ if(sym->flags & SymUniq)
+ return sym->def;
+ sym->flags |= SymUniq;
+
+ xtype = nod(OTFUNC, N, N);
+ i = 0;
+ l = nil;
+ callargs = nil;
+ xfunc = nod(ODCLFUNC, N, N);
+ for(t = getinargx(t0)->type; t; t = t->down) {
+ snprint(namebuf, sizeof namebuf, "a%d", i++);
+ n = newname(lookup(namebuf));
+ n->class = PPARAM;
+ xfunc->dcl = list(xfunc->dcl, n);
+ callargs = list(callargs, n);
+ l = list(l, nod(ODCLFIELD, n, typenod(t->type)));
}
+ xtype->list = l;
+ i = 0;
+ l = nil;
+ retargs = nil;
+ for(t = getoutargx(t0)->type; t; t = t->down) {
+ snprint(namebuf, sizeof namebuf, "r%d", i++);
+ n = newname(lookup(namebuf));
+ n->class = PPARAMOUT;
+ xfunc->dcl = list(xfunc->dcl, n);
+ retargs = list(retargs, n);
+ l = list(l, nod(ODCLFIELD, n, typenod(t->type)));
+ }
+ xtype->rlist = l;
- // New arg list for n. First the closure-args
- // and then the original parameter list.
- n->list = concat(n->left->enter, n->list);
- n->left = n->left->closure->nname;
- dowidth(n->left->type);
- n->type = getoutargx(n->left->type);
- // for a single valued function, pull the field type out of the struct
- if (n->type && n->type->type && !n->type->type->down)
- n->type = n->type->type->type;
+ xfunc->dupok = 1;
+ xfunc->nname = newname(sym);
+ xfunc->nname->sym->flags |= SymExported; // disable export
+ xfunc->nname->ntype = xtype;
+ xfunc->nname->defn = xfunc;
+ declare(xfunc->nname, PFUNC);
+
+ // Declare and initialize variable holding receiver.
+ body = nil;
+ cv = nod(OCLOSUREVAR, N, N);
+ cv->xoffset = widthptr;
+ cv->type = rcvrtype;
+ ptr = nod(ONAME, N, N);
+ ptr->sym = lookup("rcvr");
+ ptr->class = PAUTO;
+ ptr->addable = 1;
+ ptr->ullman = 1;
+ ptr->used = 1;
+ ptr->curfn = xfunc;
+ xfunc->dcl = list(xfunc->dcl, ptr);
+ if(isptr[rcvrtype->etype] || isinter(rcvrtype)) {
+ ptr->ntype = typenod(rcvrtype);
+ body = list(body, nod(OAS, ptr, cv));
+ } else {
+ ptr->ntype = typenod(ptrto(rcvrtype));
+ body = list(body, nod(OAS, ptr, nod(OADDR, cv, N)));
+ }
+
+ call = nod(OCALL, nod(OXDOT, ptr, meth), N);
+ call->list = callargs;
+ if(t0->outtuple == 0) {
+ body = list(body, call);
+ } else {
+ n = nod(OAS2, N, N);
+ n->list = retargs;
+ n->rlist = list1(call);
+ body = list(body, n);
+ n = nod(ORETURN, N, N);
+ body = list(body, n);
+ }
+
+ xfunc->nbody = body;
+
+ typecheck(&xfunc, Etop);
+ sym->def = xfunc;
+ xtop = list(xtop, xfunc);
+
+ return xfunc;
+}
+
+Node*
+walkpartialcall(Node *n, NodeList **init)
+{
+ Node *clos, *typ;
+
+ // Create closure in the form of a composite literal.
+ // For x.M with receiver (x) type T, the generated code looks like:
+ //
+ // clos = &struct{F uintptr; R T}{M.T·f, x}
+ //
+ // Like walkclosure above.
+
+ if(isinter(n->left->type)) {
+ n->left = cheapexpr(n->left, init);
+ checknotnil(n->left, init);
+ }
+
+ typ = nod(OTSTRUCT, N, N);
+ typ->list = list1(nod(ODCLFIELD, newname(lookup("F")), typenod(types[TUINTPTR])));
+ typ->list = list(typ->list, nod(ODCLFIELD, newname(lookup("R")), typenod(n->left->type)));
+
+ clos = nod(OCOMPLIT, N, nod(OIND, typ, N));
+ clos->esc = n->esc;
+ clos->right->implicit = 1;
+ clos->list = list1(nod(OCFUNC, n->nname->nname, N));
+ clos->list = list(clos->list, n->left);
+
+ // Force type conversion from *struct to the func type.
+ clos = nod(OCONVNOP, clos, N);
+ clos->type = n->type;
+
+ typecheck(&clos, Erv);
+ // typecheck will insert a PTRLIT node under CONVNOP,
+ // tag it with escape analysis result.
+ clos->left->esc = n->esc;
+ walkexpr(&clos, init);
+
+ return clos;
}
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index 4f1ff6778..add438daf 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -119,6 +119,27 @@ convlit1(Node **np, Type *t, int explicit)
}
n->type = t;
return;
+ case OCOMPLEX:
+ if(n->type->etype == TIDEAL) {
+ switch(t->etype) {
+ default:
+ // If trying to convert to non-complex type,
+ // leave as complex128 and let typechecker complain.
+ t = types[TCOMPLEX128];
+ //fallthrough
+ case TCOMPLEX128:
+ n->type = t;
+ convlit(&n->left, types[TFLOAT64]);
+ convlit(&n->right, types[TFLOAT64]);
+ break;
+ case TCOMPLEX64:
+ n->type = t;
+ convlit(&n->left, types[TFLOAT32]);
+ convlit(&n->right, types[TFLOAT32]);
+ break;
+ }
+ }
+ return;
}
// avoided repeated calculations, errors
@@ -1068,6 +1089,11 @@ idealkind(Node *n)
return k1;
else
return k2;
+ case OREAL:
+ case OIMAG:
+ return CTFLT;
+ case OCOMPLEX:
+ return CTCPLX;
case OADDSTR:
return CTSTR;
case OANDAND:
@@ -1185,6 +1211,7 @@ void
defaultlit2(Node **lp, Node **rp, int force)
{
Node *l, *r;
+ int lkind, rkind;
l = *lp;
r = *rp;
@@ -1204,18 +1231,20 @@ defaultlit2(Node **lp, Node **rp, int force)
convlit(lp, types[TBOOL]);
convlit(rp, types[TBOOL]);
}
- if(isconst(l, CTCPLX) || isconst(r, CTCPLX)) {
+ lkind = idealkind(l);
+ rkind = idealkind(r);
+ if(lkind == CTCPLX || rkind == CTCPLX) {
convlit(lp, types[TCOMPLEX128]);
convlit(rp, types[TCOMPLEX128]);
return;
}
- if(isconst(l, CTFLT) || isconst(r, CTFLT)) {
+ if(lkind == CTFLT || rkind == CTFLT) {
convlit(lp, types[TFLOAT64]);
convlit(rp, types[TFLOAT64]);
return;
}
- if(isconst(l, CTRUNE) || isconst(r, CTRUNE)) {
+ if(lkind == CTRUNE || rkind == CTRUNE) {
convlit(lp, runetype);
convlit(rp, runetype);
return;
diff --git a/src/cmd/gc/cplx.c b/src/cmd/gc/cplx.c
index e0127fc59..c9bab7a76 100644
--- a/src/cmd/gc/cplx.c
+++ b/src/cmd/gc/cplx.c
@@ -36,7 +36,7 @@ void
complexmove(Node *f, Node *t)
{
int ft, tt;
- Node n1, n2, n3, n4;
+ Node n1, n2, n3, n4, tmp;
if(debug['g']) {
dump("\ncomplexmove-f", f);
@@ -62,9 +62,9 @@ complexmove(Node *f, Node *t)
// make f addable.
// also use temporary if possible stack overlap.
if(!f->addable || overlap(f, t)) {
- tempname(&n1, f->type);
- complexmove(f, &n1);
- f = &n1;
+ tempname(&tmp, f->type);
+ complexmove(f, &tmp);
+ f = &tmp;
}
subnode(&n1, &n2, f);
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index aa2489d9a..429f212e7 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -225,8 +225,12 @@ declare(Node *n, int ctxt)
if(ctxt == PAUTO)
n->xoffset = 0;
- if(s->block == block)
- redeclare(s, "in this block");
+ if(s->block == block) {
+ // functype will print errors about duplicate function arguments.
+ // Don't repeat the error here.
+ if(ctxt != PPARAM && ctxt != PPARAMOUT)
+ redeclare(s, "in this block");
+ }
s->block = block;
s->lastlineno = parserline();
@@ -824,22 +828,24 @@ structfield(Node *n)
return f;
}
+static uint32 uniqgen;
+
static void
checkdupfields(Type *t, char* what)
{
- Type* t1;
int lno;
lno = lineno;
- for( ; t; t=t->down)
- if(t->sym && t->nname && !isblank(t->nname))
- for(t1=t->down; t1; t1=t1->down)
- if(t1->sym == t->sym) {
- lineno = t->nname->lineno;
- yyerror("duplicate %s %s", what, t->sym->name);
- break;
- }
+ for( ; t; t=t->down) {
+ if(t->sym && t->nname && !isblank(t->nname)) {
+ if(t->sym->uniqgen == uniqgen) {
+ lineno = t->nname->lineno;
+ yyerror("duplicate %s %s", what, t->sym->name);
+ } else
+ t->sym->uniqgen = uniqgen;
+ }
+ }
lineno = lno;
}
@@ -865,6 +871,7 @@ tostruct(NodeList *l)
if(f->broke)
t->broke = 1;
+ uniqgen++;
checkdupfields(t->type, "field");
if (!t->broke)
@@ -897,7 +904,6 @@ tofunargs(NodeList *l)
if(f->broke)
t->broke = 1;
- checkdupfields(t->type, "argument");
return t;
}
@@ -1004,6 +1010,7 @@ tointerface(NodeList *l)
if(f->broke)
t->broke = 1;
+ uniqgen++;
checkdupfields(t->type, "method");
t = sortinter(t);
checkwidth(t);
@@ -1187,6 +1194,11 @@ functype(Node *this, NodeList *in, NodeList *out)
t->type->down = tofunargs(out);
t->type->down->down = tofunargs(in);
+ uniqgen++;
+ checkdupfields(t->type->type, "argument");
+ checkdupfields(t->type->down->type, "argument");
+ checkdupfields(t->type->down->down->type, "argument");
+
if (t->type->broke || t->type->down->broke || t->type->down->down->broke)
t->broke = 1;
@@ -1368,6 +1380,12 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)
}
}
+ if(local && !pa->local) {
+ // defining method on non-local type.
+ yyerror("cannot define new methods on non-local type %T", pa);
+ return;
+ }
+
n = nod(ODCLFIELD, newname(sf), N);
n->type = t;
@@ -1383,12 +1401,6 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)
return;
}
- if(local && !pa->local) {
- // defining method on non-local type.
- yyerror("cannot define new methods on non-local type %T", pa);
- return;
- }
-
f = structfield(n);
f->nointerface = nointerface;
diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c
index 46c06d10e..df273e392 100644
--- a/src/cmd/gc/esc.c
+++ b/src/cmd/gc/esc.c
@@ -596,6 +596,14 @@ esc(EscState *e, Node *n)
// Contents make it to memory, lose track.
escassign(e, &e->theSink, n->left);
break;
+
+ case OCALLPART:
+ n->esc = EscNone; // until proven otherwise
+ e->noesc = list(e->noesc, n);
+ n->escloopdepth = e->loopdepth;
+ // Contents make it to memory, lose track.
+ escassign(e, &e->theSink, n->left);
+ break;
case OMAPLIT:
n->esc = EscNone; // until proven otherwise
@@ -667,6 +675,7 @@ escassign(EscState *e, Node *dst, Node *src)
case OCONVNOP:
case OMAPLIT:
case OSTRUCTLIT:
+ case OCALLPART:
break;
case ONAME:
@@ -713,6 +722,7 @@ escassign(EscState *e, Node *dst, Node *src)
case OMAKESLICE:
case ONEW:
case OCLOSURE:
+ case OCALLPART:
escflows(e, dst, src);
break;
@@ -1033,7 +1043,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
switch(src->op) {
case ONAME:
- if(src->class == PPARAM && leaks && src->esc != EscHeap) {
+ if(src->class == PPARAM && (leaks || dst->escloopdepth < 0) && src->esc != EscHeap) {
src->esc = EscScope;
if(debug['m'])
warnl(src->lineno, "leaking param: %hN", src);
@@ -1073,6 +1083,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
case OMAPLIT:
case ONEW:
case OCLOSURE:
+ case OCALLPART:
if(leaks) {
src->esc = EscHeap;
if(debug['m'])
diff --git a/src/cmd/gc/fmt.c b/src/cmd/gc/fmt.c
index ab81e6c88..ee5b9e939 100644
--- a/src/cmd/gc/fmt.c
+++ b/src/cmd/gc/fmt.c
@@ -168,7 +168,7 @@ Lconv(Fmt *fp)
lno = a[i].incl->line - 1; // now print out start of this file
}
if(n == 0)
- fmtprint(fp, "<epoch>");
+ fmtprint(fp, "<unknown line number>");
return 0;
}
@@ -1022,6 +1022,7 @@ static int opprec[] = {
[ODOTTYPE] = 8,
[ODOT] = 8,
[OXDOT] = 8,
+ [OCALLPART] = 8,
[OPLUS] = 7,
[ONOT] = 7,
@@ -1269,9 +1270,10 @@ exprfmt(Fmt *f, Node *n, int prec)
case ODOTPTR:
case ODOTINTER:
case ODOTMETH:
+ case OCALLPART:
exprfmt(f, n->left, nprec);
if(n->right == N || n->right->sym == S)
- fmtstrcpy(f, ".<nil>");
+ return fmtstrcpy(f, ".<nil>");
return fmtprint(f, ".%hhS", n->right->sym);
case ODOTTYPE:
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 5f03d9476..b47a04bf0 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -491,6 +491,9 @@ gen(Node *n)
case ORETURN:
cgen_ret(n);
break;
+
+ case OCHECKNOTNIL:
+ checkref(n->left, 1);
}
ret:
@@ -807,7 +810,7 @@ cgen_slice(Node *n, Node *res)
if(n->op == OSLICEARR) {
if(!isptr[n->left->type->etype])
fatal("slicearr is supposed to work on pointer: %+N\n", n);
- checkref(n->left);
+ checkref(n->left, 0);
}
if(isnil(n->left)) {
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index f86c152f2..6be0ec8c9 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -268,6 +268,7 @@ struct Node
uchar addrtaken; // address taken, even if not moved to heap
uchar dupok; // duplicate definitions ok (for func)
schar likely; // likeliness of if statement
+ uchar hasbreak; // has break statement
// most nodes
Type* type;
@@ -368,6 +369,7 @@ struct Sym
uchar sym; // huffman encoding in object file
Sym* link;
int32 npkg; // number of imported packages with this name
+ uint32 uniqgen;
// saved and restored by dcopy
Pkg* pkg;
@@ -450,6 +452,7 @@ enum
OCALLFUNC, // f()
OCALLMETH, // t.Method()
OCALLINTER, // err.Error()
+ OCALLPART, // t.Method (without ())
OCAP, // cap
OCLOSE, // close
OCLOSURE, // f = func() { etc }
@@ -562,6 +565,7 @@ enum
OITAB, // itable word of an interface value.
OCLOSUREVAR, // variable reference at beginning of closure function
OCFUNC, // reference to c function pointer (not go func value)
+ OCHECKNOTNIL, // emit code to ensure pointer/interface not nil
// arch-specific registers
OREGISTER, // a register, such as AX.
@@ -987,7 +991,8 @@ Node* closurebody(NodeList *body);
void closurehdr(Node *ntype);
void typecheckclosure(Node *func, int top);
Node* walkclosure(Node *func, NodeList **init);
-void walkcallclosure(Node *n, NodeList **init);
+void typecheckpartialcall(Node*, Node*);
+Node* walkpartialcall(Node*, NodeList**);
/*
* const.c
@@ -1363,6 +1368,7 @@ Node* typecheck(Node **np, int top);
void typechecklist(NodeList *l, int top);
Node* typecheckdef(Node *n);
void copytype(Node *n, Type *t);
+void checkreturn(Node*);
void queuemethod(Node *n);
/*
@@ -1416,7 +1422,8 @@ EXTERN Node* nodfp;
int anyregalloc(void);
void betypeinit(void);
void bgen(Node *n, int true, int likely, Prog *to);
-void checkref(Node*);
+void checkref(Node *n, int force);
+void checknotnil(Node*, NodeList**);
void cgen(Node*, Node*);
void cgen_asop(Node *n);
void cgen_call(Node *n, int proc);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 794961e8e..a12da5671 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -536,7 +536,10 @@ compound_stmt:
}
stmt_list '}'
{
- $$ = liststmt($3);
+ if($3 == nil)
+ $$ = nod(OEMPTY, N, N);
+ else
+ $$ = liststmt($3);
popdcl();
}
diff --git a/src/cmd/gc/inl.c b/src/cmd/gc/inl.c
index 1cc13a304..850bb36ec 100644
--- a/src/cmd/gc/inl.c
+++ b/src/cmd/gc/inl.c
@@ -357,7 +357,7 @@ inlnode(Node **np)
}
case OCLOSURE:
- // TODO do them here (or earlier) instead of in walkcallclosure,
+ // TODO do them here (or earlier),
// so escape analysis can avoid more heapmoves.
return;
}
@@ -565,24 +565,31 @@ mkinlcall1(Node **np, Node *fn, int isddd)
inlretvars = nil;
i = 0;
// Make temp names to use instead of the originals
- for(ll = dcl; ll; ll=ll->next)
+ for(ll = dcl; ll; ll=ll->next) {
+ if(ll->n->class == PPARAMOUT) // return values handled below.
+ continue;
if(ll->n->op == ONAME) {
ll->n->inlvar = inlvar(ll->n);
// Typecheck because inlvar is not necessarily a function parameter.
typecheck(&ll->n->inlvar, Erv);
if ((ll->n->class&~PHEAP) != PAUTO)
ninit = list(ninit, nod(ODCL, ll->n->inlvar, N)); // otherwise gen won't emit the allocations for heapallocs
- if (ll->n->class == PPARAMOUT) // we rely on the order being correct here
- inlretvars = list(inlretvars, ll->n->inlvar);
}
+ }
- // anonymous return values, synthesize names for use in assignment that replaces return
- if(inlretvars == nil && fn->type->outtuple > 0)
- for(t = getoutargx(fn->type)->type; t; t = t->down) {
+ // temporaries for return values.
+ for(t = getoutargx(fn->type)->type; t; t = t->down) {
+ if(t != T && t->nname != N && !isblank(t->nname)) {
+ m = inlvar(t->nname);
+ typecheck(&m, Erv);
+ t->nname->inlvar = m;
+ } else {
+ // anonymous return values, synthesize names for use in assignment that replaces return
m = retvar(t, i++);
- ninit = list(ninit, nod(ODCL, m, N));
- inlretvars = list(inlretvars, m);
}
+ ninit = list(ninit, nod(ODCL, m, N));
+ inlretvars = list(inlretvars, m);
+ }
// assign receiver.
if(fn->type->thistuple && n->left->op == ODOTMETH) {
@@ -790,6 +797,12 @@ inlvar(Node *var)
n->class = PAUTO;
n->used = 1;
n->curfn = curfn; // the calling function, not the called one
+
+ // esc pass wont run if we're inlining into a iface wrapper
+ // luckily, we can steal the results from the target func
+ if(var->esc == EscHeap)
+ addrescapes(n);
+
curfn->dcl = list(curfn->dcl, n);
return n;
}
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 68ae6864d..118a0d7a0 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -376,6 +376,7 @@ main(int argc, char *argv[])
curfn = l->n;
saveerrors();
typechecklist(l->n->nbody, Etop);
+ checkreturn(l->n);
if(nerrors != 0)
l->n->nbody = nil; // type errors; do not compile
}
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index b87d35b7b..e4bcd1170 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -16,6 +16,8 @@ static void dumpglobls(void);
void
dumpobj(void)
{
+ NodeList *externs, *tmp;
+
bout = Bopen(outfile, OWRITE);
if(bout == nil) {
flusherrors();
@@ -31,8 +33,20 @@ dumpobj(void)
outhist(bout);
+ externs = nil;
+ if(externdcl != nil)
+ externs = externdcl->end;
+
dumpglobls();
dumptypestructs();
+
+ // Dump extra globals.
+ tmp = externdcl;
+ if(externs != nil)
+ externdcl = externs->next;
+ dumpglobls();
+ externdcl = tmp;
+
dumpdata();
dumpfuncs();
diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c
index bae98ec1b..3e5e592ca 100644
--- a/src/cmd/gc/racewalk.c
+++ b/src/cmd/gc/racewalk.c
@@ -196,6 +196,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OPLUS:
case OREAL:
case OIMAG:
+ case OCOM:
racewalknode(&n->left, init, wr, 0);
goto ret;
@@ -222,23 +223,17 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OCAP:
racewalknode(&n->left, init, 0, 0);
if(istype(n->left->type, TMAP)) {
- // crashes on len(m[0]) or len(f())
- SET(n1);
- USED(n1);
- /*
- n1 = nod(OADDR, n->left, N);
- n1 = conv(n1, types[TUNSAFEPTR]);
- n1 = conv(n1, ptrto(ptrto(types[TINT8])));
- n1 = nod(OIND, n1, N);
+ n1 = nod(OCONVNOP, n->left, N);
+ n1->type = ptrto(types[TUINT8]);
n1 = nod(OIND, n1, N);
typecheck(&n1, Erv);
callinstr(&n1, init, 0, skip);
- */
}
goto ret;
case OLSH:
case ORSH:
+ case OLROT:
case OAND:
case OANDNOT:
case OOR:
@@ -279,7 +274,6 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case ODIV:
case OMOD:
- // TODO(dvyukov): add a test for this
racewalknode(&n->left, init, wr, 0);
racewalknode(&n->right, init, wr, 0);
goto ret;
@@ -324,9 +318,30 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OPANIC:
case ORECOVER:
case OCONVIFACE:
+ case OMAKECHAN:
+ case OMAKEMAP:
+ case OMAKESLICE:
+ case OCALL:
+ case OCOPY:
+ case ORUNESTR:
+ case OARRAYBYTESTR:
+ case OARRAYRUNESTR:
+ case OSTRARRAYBYTE:
+ case OSTRARRAYRUNE:
+ case OINDEXMAP: // lowered to call
+ case OCMPSTR:
+ case OADDSTR:
+ case ODOTTYPE:
+ case ODOTTYPE2:
yyerror("racewalk: %O must be lowered by now", n->op);
goto ret;
+ // impossible nodes: only appear in backend.
+ case ORROTC:
+ case OEXTEND:
+ yyerror("racewalk: %O cannot exist now", n->op);
+ goto ret;
+
// just do generic traversal
case OFOR:
case OIF:
@@ -334,43 +349,28 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case ORETURN:
case OSELECT:
case OEMPTY:
+ case OBREAK:
+ case OCONTINUE:
+ case OFALL:
+ case OGOTO:
+ case OLABEL:
goto ret;
// does not require instrumentation
- case OINDEXMAP: // implemented in runtime
case OPRINT: // don't bother instrumenting it
case OPRINTN: // don't bother instrumenting it
case OPARAM: // it appears only in fn->exit to copy heap params back
goto ret;
// unimplemented
- case OCMPSTR:
- case OADDSTR:
case OSLICESTR:
case OAPPEND:
- case OCOPY:
- case OMAKECHAN:
- case OMAKEMAP:
- case OMAKESLICE:
- case ORUNESTR:
- case OARRAYBYTESTR:
- case OARRAYRUNESTR:
- case OSTRARRAYBYTE:
- case OSTRARRAYRUNE:
case OCMPIFACE:
case OARRAYLIT:
case OMAPLIT:
case OSTRUCTLIT:
case OCLOSURE:
- case ODOTTYPE:
- case ODOTTYPE2:
- case OCALL:
- case OBREAK:
case ODCL:
- case OCONTINUE:
- case OFALL:
- case OGOTO:
- case OLABEL:
case ODCLCONST:
case ODCLTYPE:
case OLITERAL:
@@ -378,13 +378,11 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OTYPE:
case ONONAME:
case OINDREG:
- case OCOM:
case ODOTMETH:
case OITAB:
- case OEXTEND:
case OHMUL:
- case OLROT:
- case ORROTC:
+ case OCHECKNOTNIL:
+ case OCLOSUREVAR:
goto ret;
}
diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c
index 50c4617c0..e80a8c723 100644
--- a/src/cmd/gc/range.c
+++ b/src/cmd/gc/range.c
@@ -182,8 +182,8 @@ walkrange(Node *n)
th = typ(TARRAY);
th->type = ptrto(types[TUINT8]);
// see ../../pkg/runtime/hashmap.h:/hash_iter
- // Size in words.
- th->bound = 5 + 4*3 + 4*4/widthptr;
+ // Size of hash_iter in # of pointers.
+ th->bound = 10;
hit = temp(th);
fn = syslook("mapiterinit", 1);
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index b8eb79938..8b546e235 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -1026,10 +1026,23 @@ dalgsym(Type *t)
}
static int
+gcinline(Type *t) {
+ switch(t->etype) {
+ case TARRAY:
+ if(t->bound == 1)
+ return 1;
+ if(t->width <= 4*widthptr)
+ return 1;
+ break;
+ }
+ return 0;
+}
+
+static int
dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
{
Type *t1;
- vlong o, off2, fieldoffset;
+ vlong o, off2, fieldoffset, i;
if(t->align > 0 && (*off % t->align) != 0)
fatal("dgcsym1: invalid initial alignment, %T", t);
@@ -1069,7 +1082,6 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
*off += t->width;
break;
- case TCHAN:
case TUNSAFEPTR:
case TFUNC:
if(*off % widthptr != 0)
@@ -1079,6 +1091,16 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
*off += t->width;
break;
+ // struct Hchan*
+ case TCHAN:
+ if(*off % widthptr != 0)
+ fatal("dgcsym1: invalid alignment, %T", t);
+ ot = duintptr(s, ot, GC_CHAN_PTR);
+ ot = duintptr(s, ot, *off);
+ ot = dsymptr(s, ot, dtypesym(t), 0);
+ *off += t->width;
+ break;
+
// struct Hmap*
case TMAP:
if(*off % widthptr != 0)
@@ -1132,8 +1154,9 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
} else {
if(t->bound < 1 || !haspointers(t->type)) {
*off += t->width;
- } else if(t->bound == 1) {
- ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1
+ } else if(gcinline(t)) {
+ for(i=0; i<t->bound; i++)
+ ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1
} else {
if(stack_size < GC_STACK_CAPACITY) {
ot = duintptr(s, ot, GC_ARRAY_START); // a stack push during GC
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index c53eaf285..796851f1a 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -2565,6 +2565,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
fn->dupok = 1;
typecheck(&fn, Etop);
typechecklist(fn->nbody, Etop);
+ inlcalls(fn);
curfn = nil;
funccompile(fn, 0);
}
@@ -3722,3 +3723,17 @@ isbadimport(Strlit *path)
}
return 0;
}
+
+void
+checknotnil(Node *x, NodeList **init)
+{
+ Node *n;
+
+ if(isinter(x->type)) {
+ x = nod(OITAB, x, N);
+ typecheck(&x, Erv);
+ }
+ n = nod(OCHECKNOTNIL, x, N);
+ n->typecheck = 1;
+ *init = list(*init, n);
+}
diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c
index a497b8622..5fba73140 100644
--- a/src/cmd/gc/swt.c
+++ b/src/cmd/gc/swt.c
@@ -322,6 +322,10 @@ casebody(Node *sw, Node *typeswvar)
setlineno(last);
yyerror("cannot fallthrough in type switch");
}
+ if(l->next == nil) {
+ setlineno(last);
+ yyerror("cannot fallthrough final case in switch");
+ }
last->op = OFALL;
} else
stat = list(stat, br);
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index fbab85d03..938716e21 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -276,6 +276,29 @@ callrecvlist(NodeList *l)
return 0;
}
+// indexlit implements typechecking of untyped values as
+// array/slice indexes. It is equivalent to defaultlit
+// except for constants of numerical kind, which are acceptable
+// whenever they can be represented by a value of type int.
+static void
+indexlit(Node **np)
+{
+ Node *n;
+
+ n = *np;
+ if(n == N || !isideal(n->type))
+ return;
+ switch(consttype(n)) {
+ case CTINT:
+ case CTRUNE:
+ case CTFLT:
+ case CTCPLX:
+ defaultlit(np, types[TINT]);
+ break;
+ }
+ defaultlit(np, T);
+}
+
static void
typecheck1(Node **np, int top)
{
@@ -732,6 +755,7 @@ reswitch:
yyerror("rhs of . must be a name"); // impossible
goto error;
}
+ r = n->right;
if(n->left->op == OTYPE) {
if(!looktypedot(n, t, 0)) {
@@ -775,7 +799,12 @@ reswitch:
switch(n->op) {
case ODOTINTER:
case ODOTMETH:
- ok |= Ecall;
+ if(top&Ecall)
+ ok |= Ecall;
+ else {
+ typecheckpartialcall(n, r);
+ ok |= Erv;
+ }
break;
default:
ok |= Erv;
@@ -839,7 +868,7 @@ reswitch:
case TSTRING:
case TARRAY:
- defaultlit(&n->right, T);
+ indexlit(&n->right);
if(t->etype == TSTRING)
n->type = types[TUINT8];
else
@@ -855,8 +884,8 @@ reswitch:
yyerror("non-integer %s index %N", why, n->right);
break;
}
- if(n->right->op == OLITERAL) {
- if(mpgetfix(n->right->val.u.xval) < 0)
+ if(isconst(n->right, CTINT)) {
+ if(mpgetfix(n->right->val.u.xval) < 0)
yyerror("invalid %s index %N (index must be non-negative)", why, n->right);
else if(isfixedarray(t) && t->bound > 0 && mpgetfix(n->right->val.u.xval) >= t->bound)
yyerror("invalid array index %N (out of bounds for %d-element array)", n->right, t->bound);
@@ -932,8 +961,8 @@ reswitch:
typecheck(&n->right->left, Erv);
typecheck(&n->right->right, Erv);
defaultlit(&n->left, T);
- defaultlit(&n->right->left, T);
- defaultlit(&n->right->right, T);
+ indexlit(&n->right->left);
+ indexlit(&n->right->right);
l = n->left;
if(isfixedarray(l->type)) {
if(!islvalue(n->left)) {
@@ -1180,16 +1209,18 @@ reswitch:
if(l->type == T || r->type == T)
goto error;
defaultlit2(&l, &r, 0);
+ if(l->type == T || r->type == T)
+ goto error;
n->left = l;
n->right = r;
- if(l->type->etype != r->type->etype) {
- badcmplx:
- yyerror("invalid operation: %N (complex of types %T, %T)", n, l->type, r->type);
+ if(!eqtype(l->type, r->type)) {
+ yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
goto error;
}
switch(l->type->etype) {
default:
- goto badcmplx;
+ yyerror("invalid operation: %N (arguments have type %T, expected floating-point)", n, l->type, r->type);
+ goto error;
case TIDEAL:
t = types[TIDEAL];
break;
@@ -1692,10 +1723,6 @@ ret:
yyerror("%N is not a type", n);
goto error;
}
- if((ok & Ecall) && !(top & Ecall)) {
- yyerror("method %N is not an expression, must be called", n);
- goto error;
- }
// TODO(rsc): simplify
if((top & (Ecall|Erv|Etype)) && !(top & Etop) && !(ok & (Erv|Etype|Ecall))) {
yyerror("%N used as value", n);
@@ -2558,6 +2585,7 @@ islvalue(Node *n)
// fall through
case OIND:
case ODOTPTR:
+ case OCLOSUREVAR:
return 1;
case ODOT:
return islvalue(n->left);
@@ -3144,3 +3172,148 @@ checkmake(Type *t, char *arg, Node *n)
}
return 0;
}
+
+static void markbreaklist(NodeList*, Node*);
+
+static void
+markbreak(Node *n, Node *implicit)
+{
+ Label *lab;
+
+ if(n == N)
+ return;
+
+ switch(n->op) {
+ case OBREAK:
+ if(n->left == N) {
+ if(implicit)
+ implicit->hasbreak = 1;
+ } else {
+ lab = n->left->sym->label;
+ if(lab != L)
+ lab->def->hasbreak = 1;
+ }
+ break;
+
+ case OFOR:
+ case OSWITCH:
+ case OTYPESW:
+ case OSELECT:
+ case ORANGE:
+ implicit = n;
+ // fall through
+
+ default:
+ markbreak(n->left, implicit);
+ markbreak(n->right, implicit);
+ markbreak(n->ntest, implicit);
+ markbreak(n->nincr, implicit);
+ markbreaklist(n->ninit, implicit);
+ markbreaklist(n->nbody, implicit);
+ markbreaklist(n->nelse, implicit);
+ markbreaklist(n->list, implicit);
+ markbreaklist(n->rlist, implicit);
+ break;
+ }
+}
+
+static void
+markbreaklist(NodeList *l, Node *implicit)
+{
+ Node *n;
+ Label *lab;
+
+ for(; l; l=l->next) {
+ n = l->n;
+ if(n->op == OLABEL && l->next && n->defn == l->next->n) {
+ switch(n->defn->op) {
+ case OFOR:
+ case OSWITCH:
+ case OTYPESW:
+ case OSELECT:
+ case ORANGE:
+ lab = mal(sizeof *lab);
+ lab->def = n->defn;
+ n->left->sym->label = lab;
+ markbreak(n->defn, n->defn);
+ n->left->sym->label = L;
+ l = l->next;
+ continue;
+ }
+ }
+ markbreak(n, implicit);
+ }
+}
+
+static int
+isterminating(NodeList *l, int top)
+{
+ int def;
+ Node *n;
+
+ if(l == nil)
+ return 0;
+ if(top) {
+ while(l->next && l->n->op != OLABEL)
+ l = l->next;
+ markbreaklist(l, nil);
+ }
+ while(l->next)
+ l = l->next;
+ n = l->n;
+
+ if(n == N)
+ return 0;
+
+ switch(n->op) {
+ // NOTE: OLABEL is treated as a separate statement,
+ // not a separate prefix, so skipping to the last statement
+ // in the block handles the labeled statement case by
+ // skipping over the label. No case OLABEL here.
+
+ case OBLOCK:
+ return isterminating(n->list, 0);
+
+ case OGOTO:
+ case ORETURN:
+ case OPANIC:
+ case OXFALL:
+ return 1;
+
+ case OFOR:
+ if(n->ntest != N)
+ return 0;
+ if(n->hasbreak)
+ return 0;
+ return 1;
+
+ case OIF:
+ return isterminating(n->nbody, 0) && isterminating(n->nelse, 0);
+
+ case OSWITCH:
+ case OTYPESW:
+ case OSELECT:
+ if(n->hasbreak)
+ return 0;
+ def = 0;
+ for(l=n->list; l; l=l->next) {
+ if(!isterminating(l->n->nbody, 0))
+ return 0;
+ if(l->n->list == nil) // default
+ def = 1;
+ }
+ if(n->op != OSELECT && !def)
+ return 0;
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+checkreturn(Node *fn)
+{
+ if(fn->type->outtuple && fn->nbody != nil)
+ if(!isterminating(fn->nbody, 1))
+ yyerrorl(fn->endlineno, "missing return at end of function");
+}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index de2105ed3..50e05fc3c 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -29,40 +29,6 @@ static void walkdiv(Node**, NodeList**);
static int bounded(Node*, int64);
static Mpint mpzero;
-// can this code branch reach the end
-// without an unconditional RETURN
-// this is hard, so it is conservative
-static int
-walkret(NodeList *l)
-{
- Node *n;
-
-loop:
- while(l && l->next)
- l = l->next;
- if(l == nil)
- return 1;
-
- // at this point, we have the last
- // statement of the function
- n = l->n;
- switch(n->op) {
- case OBLOCK:
- l = n->list;
- goto loop;
-
- case OGOTO:
- case ORETURN:
- case OPANIC:
- return 0;
- break;
- }
-
- // all other statements
- // will flow to the end
- return 1;
-}
-
void
walk(Node *fn)
{
@@ -76,9 +42,6 @@ walk(Node *fn)
snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
dumplist(s, curfn->nbody);
}
- if(curfn->type->outtuple)
- if(walkret(curfn->nbody))
- yyerror("function ends without a return statement");
lno = lineno;
@@ -221,6 +184,7 @@ walkstmt(Node **np)
case OLABEL:
case ODCLCONST:
case ODCLTYPE:
+ case OCHECKNOTNIL:
break;
case OBLOCK:
@@ -433,13 +397,28 @@ walkexpr(Node **np, NodeList **init)
case OIMAG:
case ODOTMETH:
case ODOTINTER:
+ walkexpr(&n->left, init);
+ goto ret;
+
case OIND:
+ if(n->left->type->type->width == 0) {
+ n->left = cheapexpr(n->left, init);
+ checknotnil(n->left, init);
+ }
walkexpr(&n->left, init);
goto ret;
case ODOT:
+ usefield(n);
+ walkexpr(&n->left, init);
+ goto ret;
+
case ODOTPTR:
usefield(n);
+ if(n->op == ODOTPTR && n->left->type->type->width == 0) {
+ n->left = cheapexpr(n->left, init);
+ checknotnil(n->left, init);
+ }
walkexpr(&n->left, init);
goto ret;
@@ -561,13 +540,6 @@ walkexpr(Node **np, NodeList **init)
if(n->list && n->list->n->op == OAS)
goto ret;
- /*
- if(n->left->op == OCLOSURE) {
- walkcallclosure(n, init);
- t = n->left->type;
- }
- */
-
walkexpr(&n->left, init);
walkexprlist(n->list, init);
@@ -673,8 +645,48 @@ walkexpr(Node **np, NodeList **init)
r = n->rlist->n;
walkexprlistsafe(n->list, init);
walkexpr(&r->left, init);
- fn = mapfn("mapaccess2", r->left->type);
- r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left, r->right);
+ t = r->left->type;
+ p = nil;
+ if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing.
+ switch(simsimtype(t->down)) {
+ case TINT32:
+ case TUINT32:
+ p = "mapaccess2_fast32";
+ break;
+ case TINT64:
+ case TUINT64:
+ p = "mapaccess2_fast64";
+ break;
+ case TSTRING:
+ p = "mapaccess2_faststr";
+ break;
+ }
+ }
+ if(p != nil) {
+ // from:
+ // a,b = m[i]
+ // to:
+ // var,b = mapaccess2_fast*(t, m, i)
+ // a = *var
+ a = n->list->n;
+ var = temp(ptrto(t->type));
+ var->typecheck = 1;
+
+ fn = mapfn(p, t);
+ r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, r->right);
+ n->rlist = list1(r);
+ n->op = OAS2FUNC;
+ n->list->n = var;
+ walkexpr(&n, init);
+ *init = list(*init, n);
+
+ n = nod(OAS, a, nod(OIND, var, N));
+ typecheck(&n, Etop);
+ walkexpr(&n, init);
+ goto ret;
+ }
+ fn = mapfn("mapaccess2", t);
+ r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, r->right);
n->rlist = list1(r);
n->op = OAS2FUNC;
goto as2func;
@@ -1041,7 +1053,33 @@ walkexpr(Node **np, NodeList **init)
goto ret;
t = n->left->type;
- n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right);
+ p = nil;
+ if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing.
+ switch(simsimtype(t->down)) {
+ case TINT32:
+ case TUINT32:
+ p = "mapaccess1_fast32";
+ break;
+ case TINT64:
+ case TUINT64:
+ p = "mapaccess1_fast64";
+ break;
+ case TSTRING:
+ p = "mapaccess1_faststr";
+ break;
+ }
+ }
+ if(p != nil) {
+ // use fast version. The fast versions return a pointer to the value - we need
+ // to dereference it to get the result.
+ n = mkcall1(mapfn(p, t), ptrto(t->type), init, typename(t), n->left, n->right);
+ n = nod(OIND, n, N);
+ n->type = t->type;
+ n->typecheck = 1;
+ } else {
+ // no fast version for this key
+ n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right);
+ }
goto ret;
case ORECV:
@@ -1292,6 +1330,10 @@ walkexpr(Node **np, NodeList **init)
case OCLOSURE:
n = walkclosure(n, init);
goto ret;
+
+ case OCALLPART:
+ n = walkpartialcall(n, init);
+ goto ret;
}
fatal("missing switch %O", n->op);
diff --git a/src/cmd/gc/y.tab.c b/src/cmd/gc/y.tab.c
index 75175455e..dee793998 100644
--- a/src/cmd/gc/y.tab.c
+++ b/src/cmd/gc/y.tab.c
@@ -662,35 +662,35 @@ static const yytype_uint16 yyrline[] =
304, 308, 312, 318, 324, 330, 335, 339, 343, 349,
355, 359, 363, 369, 373, 379, 380, 384, 390, 399,
405, 423, 428, 440, 456, 461, 468, 488, 506, 515,
- 534, 533, 545, 544, 575, 578, 585, 584, 595, 601,
- 610, 621, 627, 630, 638, 637, 648, 654, 666, 670,
- 675, 665, 696, 695, 708, 711, 717, 720, 732, 736,
- 731, 754, 753, 769, 770, 774, 778, 782, 786, 790,
- 794, 798, 802, 806, 810, 814, 818, 822, 826, 830,
- 834, 838, 842, 847, 853, 854, 858, 869, 873, 877,
- 881, 886, 890, 900, 904, 909, 917, 921, 922, 933,
- 937, 941, 945, 949, 950, 956, 963, 969, 976, 979,
- 986, 992, 1009, 1016, 1017, 1024, 1025, 1044, 1045, 1048,
- 1051, 1055, 1066, 1075, 1081, 1084, 1087, 1094, 1095, 1101,
- 1116, 1124, 1136, 1141, 1147, 1148, 1149, 1150, 1151, 1152,
- 1158, 1159, 1160, 1161, 1167, 1168, 1169, 1170, 1171, 1177,
- 1178, 1181, 1184, 1185, 1186, 1187, 1188, 1191, 1192, 1205,
- 1209, 1214, 1219, 1224, 1228, 1229, 1232, 1238, 1245, 1251,
- 1258, 1264, 1275, 1289, 1318, 1358, 1383, 1401, 1410, 1413,
- 1421, 1425, 1429, 1436, 1442, 1447, 1459, 1462, 1472, 1473,
- 1479, 1480, 1486, 1490, 1496, 1497, 1503, 1507, 1513, 1536,
- 1541, 1547, 1553, 1560, 1569, 1578, 1593, 1599, 1604, 1608,
- 1615, 1628, 1629, 1635, 1641, 1644, 1648, 1654, 1657, 1666,
- 1669, 1670, 1674, 1675, 1681, 1682, 1683, 1684, 1685, 1687,
- 1686, 1701, 1706, 1710, 1714, 1718, 1722, 1727, 1746, 1752,
- 1760, 1764, 1770, 1774, 1780, 1784, 1790, 1794, 1803, 1807,
- 1811, 1815, 1821, 1824, 1832, 1833, 1835, 1836, 1839, 1842,
- 1845, 1848, 1851, 1854, 1857, 1860, 1863, 1866, 1869, 1872,
- 1875, 1878, 1884, 1888, 1892, 1896, 1900, 1904, 1924, 1931,
- 1942, 1943, 1944, 1947, 1948, 1951, 1955, 1965, 1969, 1973,
- 1977, 1981, 1985, 1989, 1995, 2001, 2009, 2017, 2023, 2030,
- 2046, 2064, 2068, 2074, 2077, 2080, 2084, 2094, 2098, 2113,
- 2121, 2122, 2134, 2135, 2138, 2142, 2148, 2152, 2158, 2162
+ 534, 533, 548, 547, 578, 581, 588, 587, 598, 604,
+ 613, 624, 630, 633, 641, 640, 651, 657, 669, 673,
+ 678, 668, 699, 698, 711, 714, 720, 723, 735, 739,
+ 734, 757, 756, 772, 773, 777, 781, 785, 789, 793,
+ 797, 801, 805, 809, 813, 817, 821, 825, 829, 833,
+ 837, 841, 845, 850, 856, 857, 861, 872, 876, 880,
+ 884, 889, 893, 903, 907, 912, 920, 924, 925, 936,
+ 940, 944, 948, 952, 953, 959, 966, 972, 979, 982,
+ 989, 995, 1012, 1019, 1020, 1027, 1028, 1047, 1048, 1051,
+ 1054, 1058, 1069, 1078, 1084, 1087, 1090, 1097, 1098, 1104,
+ 1119, 1127, 1139, 1144, 1150, 1151, 1152, 1153, 1154, 1155,
+ 1161, 1162, 1163, 1164, 1170, 1171, 1172, 1173, 1174, 1180,
+ 1181, 1184, 1187, 1188, 1189, 1190, 1191, 1194, 1195, 1208,
+ 1212, 1217, 1222, 1227, 1231, 1232, 1235, 1241, 1248, 1254,
+ 1261, 1267, 1278, 1292, 1321, 1361, 1386, 1404, 1413, 1416,
+ 1424, 1428, 1432, 1439, 1445, 1450, 1462, 1465, 1475, 1476,
+ 1482, 1483, 1489, 1493, 1499, 1500, 1506, 1510, 1516, 1539,
+ 1544, 1550, 1556, 1563, 1572, 1581, 1596, 1602, 1607, 1611,
+ 1618, 1631, 1632, 1638, 1644, 1647, 1651, 1657, 1660, 1669,
+ 1672, 1673, 1677, 1678, 1684, 1685, 1686, 1687, 1688, 1690,
+ 1689, 1704, 1709, 1713, 1717, 1721, 1725, 1730, 1749, 1755,
+ 1763, 1767, 1773, 1777, 1783, 1787, 1793, 1797, 1806, 1810,
+ 1814, 1818, 1824, 1827, 1835, 1836, 1838, 1839, 1842, 1845,
+ 1848, 1851, 1854, 1857, 1860, 1863, 1866, 1869, 1872, 1875,
+ 1878, 1881, 1887, 1891, 1895, 1899, 1903, 1907, 1927, 1934,
+ 1945, 1946, 1947, 1950, 1951, 1954, 1958, 1968, 1972, 1976,
+ 1980, 1984, 1988, 1992, 1998, 2004, 2012, 2020, 2026, 2033,
+ 2049, 2067, 2071, 2077, 2080, 2083, 2087, 2097, 2101, 2116,
+ 2124, 2125, 2137, 2138, 2141, 2145, 2151, 2155, 2161, 2165
};
#endif
@@ -2867,13 +2867,16 @@ yyreduce:
case 61:
#line 538 "go.y"
{
- (yyval.node) = liststmt((yyvsp[(3) - (4)].list));
+ if((yyvsp[(3) - (4)].list) == nil)
+ (yyval.node) = nod(OEMPTY, N, N);
+ else
+ (yyval.node) = liststmt((yyvsp[(3) - (4)].list));
popdcl();
}
break;
case 62:
-#line 545 "go.y"
+#line 548 "go.y"
{
// If the last token read by the lexer was consumed
// as part of the case, clear it (parser has cleared yychar).
@@ -2886,7 +2889,7 @@ yyreduce:
break;
case 63:
-#line 555 "go.y"
+#line 558 "go.y"
{
int last;
@@ -2908,28 +2911,28 @@ yyreduce:
break;
case 64:
-#line 575 "go.y"
+#line 578 "go.y"
{
(yyval.list) = nil;
}
break;
case 65:
-#line 579 "go.y"
+#line 582 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node));
}
break;
case 66:
-#line 585 "go.y"
+#line 588 "go.y"
{
markdcl();
}
break;
case 67:
-#line 589 "go.y"
+#line 592 "go.y"
{
(yyval.list) = (yyvsp[(3) - (4)].list);
popdcl();
@@ -2937,7 +2940,7 @@ yyreduce:
break;
case 68:
-#line 596 "go.y"
+#line 599 "go.y"
{
(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2946,7 +2949,7 @@ yyreduce:
break;
case 69:
-#line 602 "go.y"
+#line 605 "go.y"
{
(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2956,7 +2959,7 @@ yyreduce:
break;
case 70:
-#line 611 "go.y"
+#line 614 "go.y"
{
// init ; test ; incr
if((yyvsp[(5) - (5)].node) != N && (yyvsp[(5) - (5)].node)->colas != 0)
@@ -2970,7 +2973,7 @@ yyreduce:
break;
case 71:
-#line 622 "go.y"
+#line 625 "go.y"
{
// normal test
(yyval.node) = nod(OFOR, N, N);
@@ -2979,7 +2982,7 @@ yyreduce:
break;
case 73:
-#line 631 "go.y"
+#line 634 "go.y"
{
(yyval.node) = (yyvsp[(1) - (2)].node);
(yyval.node)->nbody = concat((yyval.node)->nbody, (yyvsp[(2) - (2)].list));
@@ -2987,14 +2990,14 @@ yyreduce:
break;
case 74:
-#line 638 "go.y"
+#line 641 "go.y"
{
markdcl();
}
break;
case 75:
-#line 642 "go.y"
+#line 645 "go.y"
{
(yyval.node) = (yyvsp[(3) - (3)].node);
popdcl();
@@ -3002,7 +3005,7 @@ yyreduce:
break;
case 76:
-#line 649 "go.y"
+#line 652 "go.y"
{
// test
(yyval.node) = nod(OIF, N, N);
@@ -3011,7 +3014,7 @@ yyreduce:
break;
case 77:
-#line 655 "go.y"
+#line 658 "go.y"
{
// init ; test
(yyval.node) = nod(OIF, N, N);
@@ -3022,14 +3025,14 @@ yyreduce:
break;
case 78:
-#line 666 "go.y"
+#line 669 "go.y"
{
markdcl();
}
break;
case 79:
-#line 670 "go.y"
+#line 673 "go.y"
{
if((yyvsp[(3) - (3)].node)->ntest == N)
yyerror("missing condition in if statement");
@@ -3037,14 +3040,14 @@ yyreduce:
break;
case 80:
-#line 675 "go.y"
+#line 678 "go.y"
{
(yyvsp[(3) - (5)].node)->nbody = (yyvsp[(5) - (5)].list);
}
break;
case 81:
-#line 679 "go.y"
+#line 682 "go.y"
{
Node *n;
NodeList *nn;
@@ -3062,14 +3065,14 @@ yyreduce:
break;
case 82:
-#line 696 "go.y"
+#line 699 "go.y"
{
markdcl();
}
break;
case 83:
-#line 700 "go.y"
+#line 703 "go.y"
{
if((yyvsp[(4) - (5)].node)->ntest == N)
yyerror("missing condition in if statement");
@@ -3079,28 +3082,28 @@ yyreduce:
break;
case 84:
-#line 708 "go.y"
+#line 711 "go.y"
{
(yyval.list) = nil;
}
break;
case 85:
-#line 712 "go.y"
+#line 715 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list));
}
break;
case 86:
-#line 717 "go.y"
+#line 720 "go.y"
{
(yyval.list) = nil;
}
break;
case 87:
-#line 721 "go.y"
+#line 724 "go.y"
{
NodeList *node;
@@ -3112,14 +3115,14 @@ yyreduce:
break;
case 88:
-#line 732 "go.y"
+#line 735 "go.y"
{
markdcl();
}
break;
case 89:
-#line 736 "go.y"
+#line 739 "go.y"
{
Node *n;
n = (yyvsp[(3) - (3)].node)->ntest;
@@ -3130,7 +3133,7 @@ yyreduce:
break;
case 90:
-#line 744 "go.y"
+#line 747 "go.y"
{
(yyval.node) = (yyvsp[(3) - (7)].node);
(yyval.node)->op = OSWITCH;
@@ -3141,14 +3144,14 @@ yyreduce:
break;
case 91:
-#line 754 "go.y"
+#line 757 "go.y"
{
typesw = nod(OXXX, typesw, N);
}
break;
case 92:
-#line 758 "go.y"
+#line 761 "go.y"
{
(yyval.node) = nod(OSELECT, N, N);
(yyval.node)->lineno = typesw->lineno;
@@ -3158,154 +3161,154 @@ yyreduce:
break;
case 94:
-#line 771 "go.y"
+#line 774 "go.y"
{
(yyval.node) = nod(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 95:
-#line 775 "go.y"
+#line 778 "go.y"
{
(yyval.node) = nod(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 96:
-#line 779 "go.y"
+#line 782 "go.y"
{
(yyval.node) = nod(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 97:
-#line 783 "go.y"
+#line 786 "go.y"
{
(yyval.node) = nod(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 98:
-#line 787 "go.y"
+#line 790 "go.y"
{
(yyval.node) = nod(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 99:
-#line 791 "go.y"
+#line 794 "go.y"
{
(yyval.node) = nod(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 100:
-#line 795 "go.y"
+#line 798 "go.y"
{
(yyval.node) = nod(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 101:
-#line 799 "go.y"
+#line 802 "go.y"
{
(yyval.node) = nod(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 102:
-#line 803 "go.y"
+#line 806 "go.y"
{
(yyval.node) = nod(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 103:
-#line 807 "go.y"
+#line 810 "go.y"
{
(yyval.node) = nod(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 104:
-#line 811 "go.y"
+#line 814 "go.y"
{
(yyval.node) = nod(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 105:
-#line 815 "go.y"
+#line 818 "go.y"
{
(yyval.node) = nod(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 106:
-#line 819 "go.y"
+#line 822 "go.y"
{
(yyval.node) = nod(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 107:
-#line 823 "go.y"
+#line 826 "go.y"
{
(yyval.node) = nod(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 108:
-#line 827 "go.y"
+#line 830 "go.y"
{
(yyval.node) = nod(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 109:
-#line 831 "go.y"
+#line 834 "go.y"
{
(yyval.node) = nod(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 110:
-#line 835 "go.y"
+#line 838 "go.y"
{
(yyval.node) = nod(OANDNOT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 111:
-#line 839 "go.y"
+#line 842 "go.y"
{
(yyval.node) = nod(OLSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 112:
-#line 843 "go.y"
+#line 846 "go.y"
{
(yyval.node) = nod(ORSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 113:
-#line 848 "go.y"
+#line 851 "go.y"
{
(yyval.node) = nod(OSEND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 115:
-#line 855 "go.y"
+#line 858 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
case 116:
-#line 859 "go.y"
+#line 862 "go.y"
{
if((yyvsp[(2) - (2)].node)->op == OCOMPLIT) {
// Special case for &T{...}: turn into (*T){...}.
@@ -3319,28 +3322,28 @@ yyreduce:
break;
case 117:
-#line 870 "go.y"
+#line 873 "go.y"
{
(yyval.node) = nod(OPLUS, (yyvsp[(2) - (2)].node), N);
}
break;
case 118:
-#line 874 "go.y"
+#line 877 "go.y"
{
(yyval.node) = nod(OMINUS, (yyvsp[(2) - (2)].node), N);
}
break;
case 119:
-#line 878 "go.y"
+#line 881 "go.y"
{
(yyval.node) = nod(ONOT, (yyvsp[(2) - (2)].node), N);
}
break;
case 120:
-#line 882 "go.y"
+#line 885 "go.y"
{
yyerror("the bitwise complement operator is ^");
(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
@@ -3348,28 +3351,28 @@ yyreduce:
break;
case 121:
-#line 887 "go.y"
+#line 890 "go.y"
{
(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
}
break;
case 122:
-#line 891 "go.y"
+#line 894 "go.y"
{
(yyval.node) = nod(ORECV, (yyvsp[(2) - (2)].node), N);
}
break;
case 123:
-#line 901 "go.y"
+#line 904 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (3)].node), N);
}
break;
case 124:
-#line 905 "go.y"
+#line 908 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3377,7 +3380,7 @@ yyreduce:
break;
case 125:
-#line 910 "go.y"
+#line 913 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (6)].node), N);
(yyval.node)->list = (yyvsp[(3) - (6)].list);
@@ -3386,14 +3389,14 @@ yyreduce:
break;
case 126:
-#line 918 "go.y"
+#line 921 "go.y"
{
(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
}
break;
case 128:
-#line 923 "go.y"
+#line 926 "go.y"
{
if((yyvsp[(1) - (3)].node)->op == OPACK) {
Sym *s;
@@ -3407,35 +3410,35 @@ yyreduce:
break;
case 129:
-#line 934 "go.y"
+#line 937 "go.y"
{
(yyval.node) = nod(ODOTTYPE, (yyvsp[(1) - (5)].node), (yyvsp[(4) - (5)].node));
}
break;
case 130:
-#line 938 "go.y"
+#line 941 "go.y"
{
(yyval.node) = nod(OTYPESW, N, (yyvsp[(1) - (5)].node));
}
break;
case 131:
-#line 942 "go.y"
+#line 945 "go.y"
{
(yyval.node) = nod(OINDEX, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
}
break;
case 132:
-#line 946 "go.y"
+#line 949 "go.y"
{
(yyval.node) = nod(OSLICE, (yyvsp[(1) - (6)].node), nod(OKEY, (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node)));
}
break;
case 134:
-#line 951 "go.y"
+#line 954 "go.y"
{
// conversion
(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
@@ -3444,7 +3447,7 @@ yyreduce:
break;
case 135:
-#line 957 "go.y"
+#line 960 "go.y"
{
(yyval.node) = (yyvsp[(3) - (5)].node);
(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3454,7 +3457,7 @@ yyreduce:
break;
case 136:
-#line 964 "go.y"
+#line 967 "go.y"
{
(yyval.node) = (yyvsp[(3) - (5)].node);
(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3463,7 +3466,7 @@ yyreduce:
break;
case 137:
-#line 970 "go.y"
+#line 973 "go.y"
{
yyerror("cannot parenthesize type in composite literal");
(yyval.node) = (yyvsp[(5) - (7)].node);
@@ -3473,7 +3476,7 @@ yyreduce:
break;
case 139:
-#line 979 "go.y"
+#line 982 "go.y"
{
// composite expression.
// make node early so we get the right line number.
@@ -3482,14 +3485,14 @@ yyreduce:
break;
case 140:
-#line 987 "go.y"
+#line 990 "go.y"
{
(yyval.node) = nod(OKEY, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 141:
-#line 993 "go.y"
+#line 996 "go.y"
{
// These nodes do not carry line numbers.
// Since a composite literal commonly spans several lines,
@@ -3509,7 +3512,7 @@ yyreduce:
break;
case 142:
-#line 1010 "go.y"
+#line 1013 "go.y"
{
(yyval.node) = (yyvsp[(2) - (4)].node);
(yyval.node)->list = (yyvsp[(3) - (4)].list);
@@ -3517,7 +3520,7 @@ yyreduce:
break;
case 144:
-#line 1018 "go.y"
+#line 1021 "go.y"
{
(yyval.node) = (yyvsp[(2) - (4)].node);
(yyval.node)->list = (yyvsp[(3) - (4)].list);
@@ -3525,7 +3528,7 @@ yyreduce:
break;
case 146:
-#line 1026 "go.y"
+#line 1029 "go.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
@@ -3545,21 +3548,21 @@ yyreduce:
break;
case 150:
-#line 1052 "go.y"
+#line 1055 "go.y"
{
(yyval.i) = LBODY;
}
break;
case 151:
-#line 1056 "go.y"
+#line 1059 "go.y"
{
(yyval.i) = '{';
}
break;
case 152:
-#line 1067 "go.y"
+#line 1070 "go.y"
{
if((yyvsp[(1) - (1)].sym) == S)
(yyval.node) = N;
@@ -3569,21 +3572,21 @@ yyreduce:
break;
case 153:
-#line 1076 "go.y"
+#line 1079 "go.y"
{
(yyval.node) = dclname((yyvsp[(1) - (1)].sym));
}
break;
case 154:
-#line 1081 "go.y"
+#line 1084 "go.y"
{
(yyval.node) = N;
}
break;
case 156:
-#line 1088 "go.y"
+#line 1091 "go.y"
{
(yyval.sym) = (yyvsp[(1) - (1)].sym);
// during imports, unqualified non-exported identifiers are from builtinpkg
@@ -3593,14 +3596,14 @@ yyreduce:
break;
case 158:
-#line 1096 "go.y"
+#line 1099 "go.y"
{
(yyval.sym) = S;
}
break;
case 159:
-#line 1102 "go.y"
+#line 1105 "go.y"
{
Pkg *p;
@@ -3616,7 +3619,7 @@ yyreduce:
break;
case 160:
-#line 1117 "go.y"
+#line 1120 "go.y"
{
(yyval.node) = oldname((yyvsp[(1) - (1)].sym));
if((yyval.node)->pack != N)
@@ -3625,7 +3628,7 @@ yyreduce:
break;
case 162:
-#line 1137 "go.y"
+#line 1140 "go.y"
{
yyerror("final argument in variadic function missing type");
(yyval.node) = nod(ODDD, typenod(typ(TINTER)), N);
@@ -3633,35 +3636,35 @@ yyreduce:
break;
case 163:
-#line 1142 "go.y"
+#line 1145 "go.y"
{
(yyval.node) = nod(ODDD, (yyvsp[(2) - (2)].node), N);
}
break;
case 169:
-#line 1153 "go.y"
+#line 1156 "go.y"
{
(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
}
break;
case 173:
-#line 1162 "go.y"
+#line 1165 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
case 178:
-#line 1172 "go.y"
+#line 1175 "go.y"
{
(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
}
break;
case 188:
-#line 1193 "go.y"
+#line 1196 "go.y"
{
if((yyvsp[(1) - (3)].node)->op == OPACK) {
Sym *s;
@@ -3675,14 +3678,14 @@ yyreduce:
break;
case 189:
-#line 1206 "go.y"
+#line 1209 "go.y"
{
(yyval.node) = nod(OTARRAY, (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].node));
}
break;
case 190:
-#line 1210 "go.y"
+#line 1213 "go.y"
{
// array literal of nelem
(yyval.node) = nod(OTARRAY, nod(ODDD, N, N), (yyvsp[(4) - (4)].node));
@@ -3690,7 +3693,7 @@ yyreduce:
break;
case 191:
-#line 1215 "go.y"
+#line 1218 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(2) - (2)].node), N);
(yyval.node)->etype = Cboth;
@@ -3698,7 +3701,7 @@ yyreduce:
break;
case 192:
-#line 1220 "go.y"
+#line 1223 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
(yyval.node)->etype = Csend;
@@ -3706,21 +3709,21 @@ yyreduce:
break;
case 193:
-#line 1225 "go.y"
+#line 1228 "go.y"
{
(yyval.node) = nod(OTMAP, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
}
break;
case 196:
-#line 1233 "go.y"
+#line 1236 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
case 197:
-#line 1239 "go.y"
+#line 1242 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
(yyval.node)->etype = Crecv;
@@ -3728,7 +3731,7 @@ yyreduce:
break;
case 198:
-#line 1246 "go.y"
+#line 1249 "go.y"
{
(yyval.node) = nod(OTSTRUCT, N, N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3737,7 +3740,7 @@ yyreduce:
break;
case 199:
-#line 1252 "go.y"
+#line 1255 "go.y"
{
(yyval.node) = nod(OTSTRUCT, N, N);
fixlbrace((yyvsp[(2) - (3)].i));
@@ -3745,7 +3748,7 @@ yyreduce:
break;
case 200:
-#line 1259 "go.y"
+#line 1262 "go.y"
{
(yyval.node) = nod(OTINTER, N, N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3754,7 +3757,7 @@ yyreduce:
break;
case 201:
-#line 1265 "go.y"
+#line 1268 "go.y"
{
(yyval.node) = nod(OTINTER, N, N);
fixlbrace((yyvsp[(2) - (3)].i));
@@ -3762,7 +3765,7 @@ yyreduce:
break;
case 202:
-#line 1276 "go.y"
+#line 1279 "go.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
if((yyval.node) == N)
@@ -3777,7 +3780,7 @@ yyreduce:
break;
case 203:
-#line 1290 "go.y"
+#line 1293 "go.y"
{
Node *t;
@@ -3809,7 +3812,7 @@ yyreduce:
break;
case 204:
-#line 1319 "go.y"
+#line 1322 "go.y"
{
Node *rcvr, *t;
@@ -3850,7 +3853,7 @@ yyreduce:
break;
case 205:
-#line 1359 "go.y"
+#line 1362 "go.y"
{
Sym *s;
Type *t;
@@ -3878,7 +3881,7 @@ yyreduce:
break;
case 206:
-#line 1384 "go.y"
+#line 1387 "go.y"
{
(yyval.node) = methodname1(newname((yyvsp[(4) - (8)].sym)), (yyvsp[(2) - (8)].list)->n->right);
(yyval.node)->type = functype((yyvsp[(2) - (8)].list)->n, (yyvsp[(6) - (8)].list), (yyvsp[(8) - (8)].list));
@@ -3897,7 +3900,7 @@ yyreduce:
break;
case 207:
-#line 1402 "go.y"
+#line 1405 "go.y"
{
(yyvsp[(3) - (5)].list) = checkarglist((yyvsp[(3) - (5)].list), 1);
(yyval.node) = nod(OTFUNC, N, N);
@@ -3907,14 +3910,14 @@ yyreduce:
break;
case 208:
-#line 1410 "go.y"
+#line 1413 "go.y"
{
(yyval.list) = nil;
}
break;
case 209:
-#line 1414 "go.y"
+#line 1417 "go.y"
{
(yyval.list) = (yyvsp[(2) - (3)].list);
if((yyval.list) == nil)
@@ -3923,21 +3926,21 @@ yyreduce:
break;
case 210:
-#line 1422 "go.y"
+#line 1425 "go.y"
{
(yyval.list) = nil;
}
break;
case 211:
-#line 1426 "go.y"
+#line 1429 "go.y"
{
(yyval.list) = list1(nod(ODCLFIELD, N, (yyvsp[(1) - (1)].node)));
}
break;
case 212:
-#line 1430 "go.y"
+#line 1433 "go.y"
{
(yyvsp[(2) - (3)].list) = checkarglist((yyvsp[(2) - (3)].list), 0);
(yyval.list) = (yyvsp[(2) - (3)].list);
@@ -3945,14 +3948,14 @@ yyreduce:
break;
case 213:
-#line 1437 "go.y"
+#line 1440 "go.y"
{
closurehdr((yyvsp[(1) - (1)].node));
}
break;
case 214:
-#line 1443 "go.y"
+#line 1446 "go.y"
{
(yyval.node) = closurebody((yyvsp[(3) - (4)].list));
fixlbrace((yyvsp[(2) - (4)].i));
@@ -3960,21 +3963,21 @@ yyreduce:
break;
case 215:
-#line 1448 "go.y"
+#line 1451 "go.y"
{
(yyval.node) = closurebody(nil);
}
break;
case 216:
-#line 1459 "go.y"
+#line 1462 "go.y"
{
(yyval.list) = nil;
}
break;
case 217:
-#line 1463 "go.y"
+#line 1466 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].list));
if(nsyntaxerrors == 0)
@@ -3985,56 +3988,56 @@ yyreduce:
break;
case 219:
-#line 1474 "go.y"
+#line 1477 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
case 221:
-#line 1481 "go.y"
+#line 1484 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
case 222:
-#line 1487 "go.y"
+#line 1490 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 223:
-#line 1491 "go.y"
+#line 1494 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 225:
-#line 1498 "go.y"
+#line 1501 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
case 226:
-#line 1504 "go.y"
+#line 1507 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 227:
-#line 1508 "go.y"
+#line 1511 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 228:
-#line 1514 "go.y"
+#line 1517 "go.y"
{
NodeList *l;
@@ -4060,7 +4063,7 @@ yyreduce:
break;
case 229:
-#line 1537 "go.y"
+#line 1540 "go.y"
{
(yyvsp[(1) - (2)].node)->val = (yyvsp[(2) - (2)].val);
(yyval.list) = list1((yyvsp[(1) - (2)].node));
@@ -4068,7 +4071,7 @@ yyreduce:
break;
case 230:
-#line 1542 "go.y"
+#line 1545 "go.y"
{
(yyvsp[(2) - (4)].node)->val = (yyvsp[(4) - (4)].val);
(yyval.list) = list1((yyvsp[(2) - (4)].node));
@@ -4077,7 +4080,7 @@ yyreduce:
break;
case 231:
-#line 1548 "go.y"
+#line 1551 "go.y"
{
(yyvsp[(2) - (3)].node)->right = nod(OIND, (yyvsp[(2) - (3)].node)->right, N);
(yyvsp[(2) - (3)].node)->val = (yyvsp[(3) - (3)].val);
@@ -4086,7 +4089,7 @@ yyreduce:
break;
case 232:
-#line 1554 "go.y"
+#line 1557 "go.y"
{
(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4096,7 +4099,7 @@ yyreduce:
break;
case 233:
-#line 1561 "go.y"
+#line 1564 "go.y"
{
(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4106,7 +4109,7 @@ yyreduce:
break;
case 234:
-#line 1570 "go.y"
+#line 1573 "go.y"
{
Node *n;
@@ -4118,7 +4121,7 @@ yyreduce:
break;
case 235:
-#line 1579 "go.y"
+#line 1582 "go.y"
{
Pkg *pkg;
@@ -4134,14 +4137,14 @@ yyreduce:
break;
case 236:
-#line 1594 "go.y"
+#line 1597 "go.y"
{
(yyval.node) = embedded((yyvsp[(1) - (1)].sym));
}
break;
case 237:
-#line 1600 "go.y"
+#line 1603 "go.y"
{
(yyval.node) = nod(ODCLFIELD, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
ifacedcl((yyval.node));
@@ -4149,14 +4152,14 @@ yyreduce:
break;
case 238:
-#line 1605 "go.y"
+#line 1608 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(1) - (1)].sym)));
}
break;
case 239:
-#line 1609 "go.y"
+#line 1612 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(2) - (3)].sym)));
yyerror("cannot parenthesize embedded type");
@@ -4164,7 +4167,7 @@ yyreduce:
break;
case 240:
-#line 1616 "go.y"
+#line 1619 "go.y"
{
// without func keyword
(yyvsp[(2) - (4)].list) = checkarglist((yyvsp[(2) - (4)].list), 1);
@@ -4175,7 +4178,7 @@ yyreduce:
break;
case 242:
-#line 1630 "go.y"
+#line 1633 "go.y"
{
(yyval.node) = nod(ONONAME, N, N);
(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4184,7 +4187,7 @@ yyreduce:
break;
case 243:
-#line 1636 "go.y"
+#line 1639 "go.y"
{
(yyval.node) = nod(ONONAME, N, N);
(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4193,56 +4196,56 @@ yyreduce:
break;
case 245:
-#line 1645 "go.y"
+#line 1648 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 246:
-#line 1649 "go.y"
+#line 1652 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 247:
-#line 1654 "go.y"
+#line 1657 "go.y"
{
(yyval.list) = nil;
}
break;
case 248:
-#line 1658 "go.y"
+#line 1661 "go.y"
{
(yyval.list) = (yyvsp[(1) - (2)].list);
}
break;
case 249:
-#line 1666 "go.y"
+#line 1669 "go.y"
{
(yyval.node) = N;
}
break;
case 251:
-#line 1671 "go.y"
+#line 1674 "go.y"
{
(yyval.node) = liststmt((yyvsp[(1) - (1)].list));
}
break;
case 253:
-#line 1676 "go.y"
+#line 1679 "go.y"
{
(yyval.node) = N;
}
break;
case 259:
-#line 1687 "go.y"
+#line 1690 "go.y"
{
(yyvsp[(1) - (2)].node) = nod(OLABEL, (yyvsp[(1) - (2)].node), N);
(yyvsp[(1) - (2)].node)->sym = dclstack; // context, for goto restrictions
@@ -4250,7 +4253,7 @@ yyreduce:
break;
case 260:
-#line 1692 "go.y"
+#line 1695 "go.y"
{
NodeList *l;
@@ -4263,7 +4266,7 @@ yyreduce:
break;
case 261:
-#line 1702 "go.y"
+#line 1705 "go.y"
{
// will be converted to OFALL
(yyval.node) = nod(OXFALL, N, N);
@@ -4271,35 +4274,35 @@ yyreduce:
break;
case 262:
-#line 1707 "go.y"
+#line 1710 "go.y"
{
(yyval.node) = nod(OBREAK, (yyvsp[(2) - (2)].node), N);
}
break;
case 263:
-#line 1711 "go.y"
+#line 1714 "go.y"
{
(yyval.node) = nod(OCONTINUE, (yyvsp[(2) - (2)].node), N);
}
break;
case 264:
-#line 1715 "go.y"
+#line 1718 "go.y"
{
(yyval.node) = nod(OPROC, (yyvsp[(2) - (2)].node), N);
}
break;
case 265:
-#line 1719 "go.y"
+#line 1722 "go.y"
{
(yyval.node) = nod(ODEFER, (yyvsp[(2) - (2)].node), N);
}
break;
case 266:
-#line 1723 "go.y"
+#line 1726 "go.y"
{
(yyval.node) = nod(OGOTO, (yyvsp[(2) - (2)].node), N);
(yyval.node)->sym = dclstack; // context, for goto restrictions
@@ -4307,7 +4310,7 @@ yyreduce:
break;
case 267:
-#line 1728 "go.y"
+#line 1731 "go.y"
{
(yyval.node) = nod(ORETURN, N, N);
(yyval.node)->list = (yyvsp[(2) - (2)].list);
@@ -4327,7 +4330,7 @@ yyreduce:
break;
case 268:
-#line 1747 "go.y"
+#line 1750 "go.y"
{
(yyval.list) = nil;
if((yyvsp[(1) - (1)].node) != N)
@@ -4336,7 +4339,7 @@ yyreduce:
break;
case 269:
-#line 1753 "go.y"
+#line 1756 "go.y"
{
(yyval.list) = (yyvsp[(1) - (3)].list);
if((yyvsp[(3) - (3)].node) != N)
@@ -4345,189 +4348,189 @@ yyreduce:
break;
case 270:
-#line 1761 "go.y"
+#line 1764 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 271:
-#line 1765 "go.y"
+#line 1768 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 272:
-#line 1771 "go.y"
+#line 1774 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 273:
-#line 1775 "go.y"
+#line 1778 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 274:
-#line 1781 "go.y"
+#line 1784 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 275:
-#line 1785 "go.y"
+#line 1788 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 276:
-#line 1791 "go.y"
+#line 1794 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 277:
-#line 1795 "go.y"
+#line 1798 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 278:
-#line 1804 "go.y"
+#line 1807 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 279:
-#line 1808 "go.y"
+#line 1811 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 280:
-#line 1812 "go.y"
+#line 1815 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 281:
-#line 1816 "go.y"
+#line 1819 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 282:
-#line 1821 "go.y"
+#line 1824 "go.y"
{
(yyval.list) = nil;
}
break;
case 283:
-#line 1825 "go.y"
+#line 1828 "go.y"
{
(yyval.list) = (yyvsp[(1) - (2)].list);
}
break;
case 288:
-#line 1839 "go.y"
+#line 1842 "go.y"
{
(yyval.node) = N;
}
break;
case 290:
-#line 1845 "go.y"
+#line 1848 "go.y"
{
(yyval.list) = nil;
}
break;
case 292:
-#line 1851 "go.y"
+#line 1854 "go.y"
{
(yyval.node) = N;
}
break;
case 294:
-#line 1857 "go.y"
+#line 1860 "go.y"
{
(yyval.list) = nil;
}
break;
case 296:
-#line 1863 "go.y"
+#line 1866 "go.y"
{
(yyval.list) = nil;
}
break;
case 298:
-#line 1869 "go.y"
+#line 1872 "go.y"
{
(yyval.list) = nil;
}
break;
case 300:
-#line 1875 "go.y"
+#line 1878 "go.y"
{
(yyval.val).ctype = CTxxx;
}
break;
case 302:
-#line 1885 "go.y"
+#line 1888 "go.y"
{
importimport((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].val).u.sval);
}
break;
case 303:
-#line 1889 "go.y"
+#line 1892 "go.y"
{
importvar((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].type));
}
break;
case 304:
-#line 1893 "go.y"
+#line 1896 "go.y"
{
importconst((yyvsp[(2) - (5)].sym), types[TIDEAL], (yyvsp[(4) - (5)].node));
}
break;
case 305:
-#line 1897 "go.y"
+#line 1900 "go.y"
{
importconst((yyvsp[(2) - (6)].sym), (yyvsp[(3) - (6)].type), (yyvsp[(5) - (6)].node));
}
break;
case 306:
-#line 1901 "go.y"
+#line 1904 "go.y"
{
importtype((yyvsp[(2) - (4)].type), (yyvsp[(3) - (4)].type));
}
break;
case 307:
-#line 1905 "go.y"
+#line 1908 "go.y"
{
if((yyvsp[(2) - (4)].node) == N) {
dclcontext = PEXTERN; // since we skip the funcbody below
@@ -4548,7 +4551,7 @@ yyreduce:
break;
case 308:
-#line 1925 "go.y"
+#line 1928 "go.y"
{
(yyval.sym) = (yyvsp[(1) - (1)].sym);
structpkg = (yyval.sym)->pkg;
@@ -4556,7 +4559,7 @@ yyreduce:
break;
case 309:
-#line 1932 "go.y"
+#line 1935 "go.y"
{
(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
importsym((yyvsp[(1) - (1)].sym), OTYPE);
@@ -4564,14 +4567,14 @@ yyreduce:
break;
case 315:
-#line 1952 "go.y"
+#line 1955 "go.y"
{
(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
}
break;
case 316:
-#line 1956 "go.y"
+#line 1959 "go.y"
{
// predefined name like uint8
(yyvsp[(1) - (1)].sym) = pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg);
@@ -4584,49 +4587,49 @@ yyreduce:
break;
case 317:
-#line 1966 "go.y"
+#line 1969 "go.y"
{
(yyval.type) = aindex(N, (yyvsp[(3) - (3)].type));
}
break;
case 318:
-#line 1970 "go.y"
+#line 1973 "go.y"
{
(yyval.type) = aindex(nodlit((yyvsp[(2) - (4)].val)), (yyvsp[(4) - (4)].type));
}
break;
case 319:
-#line 1974 "go.y"
+#line 1977 "go.y"
{
(yyval.type) = maptype((yyvsp[(3) - (5)].type), (yyvsp[(5) - (5)].type));
}
break;
case 320:
-#line 1978 "go.y"
+#line 1981 "go.y"
{
(yyval.type) = tostruct((yyvsp[(3) - (4)].list));
}
break;
case 321:
-#line 1982 "go.y"
+#line 1985 "go.y"
{
(yyval.type) = tointerface((yyvsp[(3) - (4)].list));
}
break;
case 322:
-#line 1986 "go.y"
+#line 1989 "go.y"
{
(yyval.type) = ptrto((yyvsp[(2) - (2)].type));
}
break;
case 323:
-#line 1990 "go.y"
+#line 1993 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(2) - (2)].type);
@@ -4635,7 +4638,7 @@ yyreduce:
break;
case 324:
-#line 1996 "go.y"
+#line 1999 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (4)].type);
@@ -4644,7 +4647,7 @@ yyreduce:
break;
case 325:
-#line 2002 "go.y"
+#line 2005 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4653,7 +4656,7 @@ yyreduce:
break;
case 326:
-#line 2010 "go.y"
+#line 2013 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4662,14 +4665,14 @@ yyreduce:
break;
case 327:
-#line 2018 "go.y"
+#line 2021 "go.y"
{
(yyval.type) = functype(nil, (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list));
}
break;
case 328:
-#line 2024 "go.y"
+#line 2027 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(2) - (3)].type)));
if((yyvsp[(1) - (3)].sym))
@@ -4679,7 +4682,7 @@ yyreduce:
break;
case 329:
-#line 2031 "go.y"
+#line 2034 "go.y"
{
Type *t;
@@ -4696,7 +4699,7 @@ yyreduce:
break;
case 330:
-#line 2047 "go.y"
+#line 2050 "go.y"
{
Sym *s;
@@ -4715,49 +4718,49 @@ yyreduce:
break;
case 331:
-#line 2065 "go.y"
+#line 2068 "go.y"
{
(yyval.node) = nod(ODCLFIELD, newname((yyvsp[(1) - (5)].sym)), typenod(functype(fakethis(), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list))));
}
break;
case 332:
-#line 2069 "go.y"
+#line 2072 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type)));
}
break;
case 333:
-#line 2074 "go.y"
+#line 2077 "go.y"
{
(yyval.list) = nil;
}
break;
case 335:
-#line 2081 "go.y"
+#line 2084 "go.y"
{
(yyval.list) = (yyvsp[(2) - (3)].list);
}
break;
case 336:
-#line 2085 "go.y"
+#line 2088 "go.y"
{
(yyval.list) = list1(nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type))));
}
break;
case 337:
-#line 2095 "go.y"
+#line 2098 "go.y"
{
(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
}
break;
case 338:
-#line 2099 "go.y"
+#line 2102 "go.y"
{
(yyval.node) = nodlit((yyvsp[(2) - (2)].val));
switch((yyval.node)->val.ctype){
@@ -4775,7 +4778,7 @@ yyreduce:
break;
case 339:
-#line 2114 "go.y"
+#line 2117 "go.y"
{
(yyval.node) = oldname(pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg));
if((yyval.node)->op != OLITERAL)
@@ -4784,7 +4787,7 @@ yyreduce:
break;
case 341:
-#line 2123 "go.y"
+#line 2126 "go.y"
{
if((yyvsp[(2) - (5)].node)->val.ctype == CTRUNE && (yyvsp[(4) - (5)].node)->val.ctype == CTINT) {
(yyval.node) = (yyvsp[(2) - (5)].node);
@@ -4798,42 +4801,42 @@ yyreduce:
break;
case 344:
-#line 2139 "go.y"
+#line 2142 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 345:
-#line 2143 "go.y"
+#line 2146 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 346:
-#line 2149 "go.y"
+#line 2152 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 347:
-#line 2153 "go.y"
+#line 2156 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 348:
-#line 2159 "go.y"
+#line 2162 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 349:
-#line 2163 "go.y"
+#line 2166 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
@@ -4841,7 +4844,7 @@ yyreduce:
/* Line 1267 of yacc.c. */
-#line 4846 "y.tab.c"
+#line 4849 "y.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -5055,7 +5058,7 @@ yyreturn:
}
-#line 2167 "go.y"
+#line 2170 "go.y"
static void
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 38fc43ef1..e7f3fb5bb 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -40,9 +40,13 @@ build writes the resulting executable to output.
Otherwise build compiles the packages but discards the results,
serving only as a check that the packages can be built.
-The -o flag specifies the output file name. If not specified, the
-name is packagename.a (for a non-main package) or the base
-name of the first source file (for a main package).
+The -o flag specifies the output file name. If not specified, the
+output file name depends on the arguments and derives from the name
+of the package, such as p.a for package p, unless p is 'main'. If
+the package is main and file names are provided, the file name
+derives from the first file name mentioned, such as f1 for 'go build
+f1.go f2.go'; with no files provided ('go build'), the output file
+name is the base name of the containing directory.
The build flags are shared by the build, install, run, and test commands:
@@ -53,6 +57,9 @@ The build flags are shared by the build, install, run, and test commands:
-p n
the number of builds that can be run in parallel.
The default is the number of CPUs available.
+ -race
+ enable data race detection.
+ Supported only on linux/amd64, darwin/amd64 and windows/amd64.
-v
print the names of packages as they are compiled.
-work
@@ -60,20 +67,22 @@ The build flags are shared by the build, install, run, and test commands:
do not delete it when exiting.
-x
print the commands.
- -race
- enable data race detection.
- Supported only on linux/amd64, darwin/amd64 and windows/amd64.
-ccflags 'arg list'
- arguments to pass on each 5c, 6c, or 8c compiler invocation
+ arguments to pass on each 5c, 6c, or 8c compiler invocation.
-compiler name
- name of compiler to use, as in runtime.Compiler (gccgo or gc)
+ name of compiler to use, as in runtime.Compiler (gccgo or gc).
-gccgoflags 'arg list'
- arguments to pass on each gccgo compiler/linker invocation
+ arguments to pass on each gccgo compiler/linker invocation.
-gcflags 'arg list'
- arguments to pass on each 5g, 6g, or 8g compiler invocation
+ arguments to pass on each 5g, 6g, or 8g compiler invocation.
+ -installsuffix suffix
+ a suffix to use in the name of the package installation directory,
+ in order to keep output separate from default builds.
+ If using the -race flag, the install suffix is automatically set to race
+ or, if set explicitly, has _race appended to it.
-ldflags 'flag list'
- arguments to pass on each 5l, 6l, or 8l linker invocation
+ arguments to pass on each 5l, 6l, or 8l linker invocation.
-tags 'tag list'
a list of build tags to consider satisfied during the build.
See the documentation for the go/build package for
@@ -153,6 +162,7 @@ func addBuildFlags(cmd *Command) {
cmd.Flag.BoolVar(&buildA, "a", false, "")
cmd.Flag.BoolVar(&buildN, "n", false, "")
cmd.Flag.IntVar(&buildP, "p", buildP, "")
+ cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "")
cmd.Flag.BoolVar(&buildV, "v", false, "")
cmd.Flag.BoolVar(&buildX, "x", false, "")
cmd.Flag.BoolVar(&buildWork, "work", false, "")
@@ -391,7 +401,9 @@ var (
func (b *builder) init() {
var err error
- b.print = fmt.Print
+ b.print = func(a ...interface{}) (int, error) {
+ return fmt.Fprint(os.Stderr, a...)
+ }
b.actionCache = make(map[cacheKey]*action)
b.mkdirCache = make(map[string]bool)
@@ -1289,7 +1301,6 @@ func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byt
return buf.Bytes(), err
}
- panic("unreachable")
}
// mkdir makes the named directory.
@@ -1632,7 +1643,7 @@ func (b *builder) libgcc(p *Package) (string, error) {
// print function to capture the command-line. This
// let's us assign it to $LIBGCC and produce a valid
// buildscript for cgo packages.
- b.print = func(a ...interface{}) (n int, err error) {
+ b.print = func(a ...interface{}) (int, error) {
return fmt.Fprint(&buf, a...)
}
}
@@ -2083,6 +2094,9 @@ func raceInit() {
buildGcflags = append(buildGcflags, "-race")
buildLdflags = append(buildLdflags, "-race")
buildCcflags = append(buildCcflags, "-D", "RACE")
- buildContext.InstallTag = "race"
+ if buildContext.InstallSuffix != "" {
+ buildContext.InstallSuffix += "_"
+ }
+ buildContext.InstallSuffix += "race"
buildContext.BuildTags = append(buildContext.BuildTags, "race")
}
diff --git a/src/cmd/go/discovery.go b/src/cmd/go/discovery.go
index d9f930867..047834050 100644
--- a/src/cmd/go/discovery.go
+++ b/src/cmd/go/discovery.go
@@ -48,7 +48,6 @@ func parseMetaGoImports(r io.Reader) (imports []metaImport) {
})
}
}
- return
}
// attrValue returns the attribute value for the case-insensitive key
diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go
index 0297b7602..a8a9b66aa 100644
--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh.
+// Edit the documentation in other files and rerun mkdoc.sh to generate this one.
+
/*
Go is a tool for managing Go source code.
@@ -56,9 +59,13 @@ build writes the resulting executable to output.
Otherwise build compiles the packages but discards the results,
serving only as a check that the packages can be built.
-The -o flag specifies the output file name. If not specified, the
-name is packagename.a (for a non-main package) or the base
-name of the first source file (for a main package).
+The -o flag specifies the output file name. If not specified, the
+output file name depends on the arguments and derives from the name
+of the package, such as p.a for package p, unless p is 'main'. If
+the package is main and file names are provided, the file name
+derives from the first file name mentioned, such as f1 for 'go build
+f1.go f2.go'; with no files provided ('go build'), the output file
+name is the base name of the containing directory.
The build flags are shared by the build, install, run, and test commands:
@@ -69,6 +76,9 @@ The build flags are shared by the build, install, run, and test commands:
-p n
the number of builds that can be run in parallel.
The default is the number of CPUs available.
+ -race
+ enable data race detection.
+ Supported only on linux/amd64, darwin/amd64 and windows/amd64.
-v
print the names of packages as they are compiled.
-work
@@ -76,20 +86,22 @@ The build flags are shared by the build, install, run, and test commands:
do not delete it when exiting.
-x
print the commands.
- -race
- enable data race detection.
- Supported only on linux/amd64, darwin/amd64 and windows/amd64.
-ccflags 'arg list'
- arguments to pass on each 5c, 6c, or 8c compiler invocation
+ arguments to pass on each 5c, 6c, or 8c compiler invocation.
-compiler name
- name of compiler to use, as in runtime.Compiler (gccgo or gc)
+ name of compiler to use, as in runtime.Compiler (gccgo or gc).
-gccgoflags 'arg list'
- arguments to pass on each gccgo compiler/linker invocation
+ arguments to pass on each gccgo compiler/linker invocation.
-gcflags 'arg list'
- arguments to pass on each 5g, 6g, or 8g compiler invocation
+ arguments to pass on each 5g, 6g, or 8g compiler invocation.
+ -installsuffix suffix
+ a suffix to use in the name of the package installation directory,
+ in order to keep output separate from default builds.
+ If using the -race flag, the install suffix is automatically set to race
+ or, if set explicitly, has _race appended to it.
-ldflags 'flag list'
- arguments to pass on each 5l, 6l, or 8l linker invocation
+ arguments to pass on each 5l, 6l, or 8l linker invocation.
-tags 'tag list'
a list of build tags to consider satisfied during the build.
See the documentation for the go/build package for
@@ -679,6 +691,11 @@ Description of testing flags
The 'go test' command takes both flags that apply to 'go test' itself
and flags that apply to the resulting test binary.
+Several of the flags control profiling and write an execution profile
+suitable for "go tool pprof"; run "go tool pprof help" for more
+information. The --alloc_space, --alloc_objects, and --show_bytes
+options of pprof control how the information is presented.
+
The following flags are recognized by the 'go test' command and
control the execution of any test:
@@ -716,8 +733,8 @@ control the execution of any test:
Write a CPU profile to the specified file before exiting.
-memprofile mem.out
- Write a memory profile to the specified file when all tests
- are complete.
+ Write a memory profile to the specified file after all tests
+ have passed.
-memprofilerate n
Enable more precise (and expensive) memory profiles by setting
diff --git a/src/cmd/go/go11.go b/src/cmd/go/go11.go
new file mode 100644
index 000000000..8a434dfed
--- /dev/null
+++ b/src/cmd/go/go11.go
@@ -0,0 +1,10 @@
+// Copyright 2013 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.
+
+// +build go1.1
+
+package main
+
+// Test that go1.1 tag above is included in builds. main.go refers to this definition.
+const go11tag = true
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
index bf1dad40f..61e629968 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -108,6 +108,7 @@ func setExitStatus(n int) {
}
func main() {
+ _ = go11tag
flag.Usage = usage
flag.Parse()
log.SetFlags(0)
@@ -129,8 +130,11 @@ func main() {
fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath)
} else {
for _, p := range filepath.SplitList(gopath) {
- if strings.Contains(p, "~") && runtime.GOOS != "windows" {
- fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot contain shell metacharacter '~': %q\n", p)
+ // Note: using HasPrefix instead of Contains because a ~ can appear
+ // in the middle of directory elements, such as /tmp/git-1.8.2~rc3
+ // or C:\PROGRA~1. Only ~ as a path prefix has meaning to the shell.
+ if strings.HasPrefix(p, "~") {
+ fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot start with shell metacharacter '~': %q\n", p)
os.Exit(2)
}
if build.IsLocalImport(p) {
@@ -189,6 +193,9 @@ var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reser
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh.
+// Edit the documentation in other files and rerun mkdoc.sh to generate this one.
+
/*
{{range .}}{{if .Short}}{{.Short | capitalize}}
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index 7fc61fd86..b33d800bf 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -72,6 +72,7 @@ type Package struct {
imports []*Package
deps []*Package
gofiles []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
+ sfiles []string
allgofiles []string // gofiles + IgnoredGoFiles, absolute paths
target string // installed file for this package (may be executable)
fake bool // synthesized package
@@ -366,6 +367,12 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
}
sort.Strings(p.gofiles)
+ p.sfiles = stringList(p.SFiles)
+ for i := range p.sfiles {
+ p.sfiles[i] = filepath.Join(p.Dir, p.sfiles[i])
+ }
+ sort.Strings(p.sfiles)
+
p.allgofiles = stringList(p.IgnoredGoFiles)
for i := range p.allgofiles {
p.allgofiles[i] = filepath.Join(p.Dir, p.allgofiles[i])
diff --git a/src/cmd/go/test.bash b/src/cmd/go/test.bash
index 460061a11..e2264a46e 100755
--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -11,18 +11,19 @@ ok=true
unset GOPATH
unset GOBIN
-# Test that error messages have file:line information
-# at beginning of line.
-for i in testdata/errmsg/*.go
-do
- # TODO: |cat should not be necessary here but is.
- ./testgo test $i 2>&1 | cat >err.out || true
- if ! grep -q "^$i:" err.out; then
- echo "$i: missing file:line in error message"
- cat err.out
- ok=false
- fi
-done
+# Test that error messages have file:line information at beginning of
+# the line. Also test issue 4917: that the error is on stderr.
+d=$(mktemp -d -t testgoXXX)
+fn=$d/err.go
+echo "package main" > $fn
+echo 'import "bar"' >> $fn
+./testgo run $fn 2>$d/err.out || true
+if ! grep -q "^$fn:" $d/err.out; then
+ echo "missing file:line in error message"
+ cat $d/err.out
+ ok=false
+fi
+rm -r $d
# Test local (./) imports.
testlocal() {
@@ -51,7 +52,7 @@ testlocal() {
ok=false
fi
- rm -f err.out hello.out hello
+ rm -f hello.out hello
# Test that go install x.go fails.
if ./testgo install "testdata/$local/easy.go" >/dev/null 2>&1; then
@@ -183,7 +184,7 @@ fi
# issue 4186. go get cannot be used to download packages to $GOROOT
# Test that without GOPATH set, go get should fail
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
mkdir -p $d/src/pkg
if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with $GOPATH unset'
@@ -191,7 +192,7 @@ if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch
fi
rm -rf $d
# Test that with GOPATH=$GOROOT, go get should fail
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
mkdir -p $d/src/pkg
if GOPATH=$d GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT'
@@ -200,7 +201,7 @@ fi
rm -rf $d
# issue 3941: args with spaces
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
cat >$d/main.go<<EOF
package main
var extern string
@@ -226,7 +227,7 @@ rm -f strings.prof strings.test
# issue 4568. test that symlinks don't screw things up too badly.
old=$(pwd)
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
mkdir -p $d/src
(
ln -s $d $d/src/dir1
@@ -247,7 +248,7 @@ fi
rm -rf $d
# issue 4515.
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
mkdir -p $d/src/example/a $d/src/example/b $d/bin
cat >$d/src/example/a/main.go <<EOF
package main
@@ -280,7 +281,7 @@ unset GOPATH
rm -rf $d
# issue 4773. case-insensitive collisions
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
export GOPATH=$d
mkdir -p $d/src/example/a $d/src/example/b
cat >$d/src/example/a/a.go <<EOF
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index 3132ab210..de69efe8f 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -81,6 +81,11 @@ var helpTestflag = &Command{
The 'go test' command takes both flags that apply to 'go test' itself
and flags that apply to the resulting test binary.
+Several of the flags control profiling and write an execution profile
+suitable for "go tool pprof"; run "go tool pprof help" for more
+information. The --alloc_space, --alloc_objects, and --show_bytes
+options of pprof control how the information is presented.
+
The following flags are recognized by the 'go test' command and
control the execution of any test:
@@ -118,8 +123,8 @@ control the execution of any test:
Write a CPU profile to the specified file before exiting.
-memprofile mem.out
- Write a memory profile to the specified file when all tests
- are complete.
+ Write a memory profile to the specified file after all tests
+ have passed.
-memprofilerate n
Enable more precise (and expensive) memory profiles by setting
diff --git a/src/cmd/go/testdata/errmsg/x.go b/src/cmd/go/testdata/errmsg/x.go
deleted file mode 100644
index 60f5b6e98..000000000
--- a/src/cmd/go/testdata/errmsg/x.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package foo
-
-import "bar"
diff --git a/src/cmd/go/testdata/errmsg/x1_test.go b/src/cmd/go/testdata/errmsg/x1_test.go
deleted file mode 100644
index eb1a6798c..000000000
--- a/src/cmd/go/testdata/errmsg/x1_test.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package foo_test
-
-import "bar"
diff --git a/src/cmd/go/testdata/errmsg/x_test.go b/src/cmd/go/testdata/errmsg/x_test.go
deleted file mode 100644
index 60f5b6e98..000000000
--- a/src/cmd/go/testdata/errmsg/x_test.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package foo
-
-import "bar"
diff --git a/src/cmd/go/vet.go b/src/cmd/go/vet.go
index eb0b89cca..503e16362 100644
--- a/src/cmd/go/vet.go
+++ b/src/cmd/go/vet.go
@@ -32,6 +32,6 @@ func runVet(cmd *Command, args []string) {
// Use pkg.gofiles instead of pkg.Dir so that
// the command only applies to this package,
// not to packages in subdirectories.
- run(tool("vet"), relPaths(pkg.gofiles))
+ run(tool("vet"), relPaths(stringList(pkg.gofiles, pkg.sfiles)))
}
}
diff --git a/src/cmd/godoc/doc.go b/src/cmd/godoc/doc.go
index ddb6d2687..e5f5324cd 100644
--- a/src/cmd/godoc/doc.go
+++ b/src/cmd/godoc/doc.go
@@ -67,6 +67,9 @@ The flags are:
-maxresults=10000
maximum number of full text search results shown
(no full text index is built if maxresults <= 0)
+ -notes="BUG"
+ regular expression matching note markers to show
+ (e.g., "BUG|TODO", ".*")
-html
print HTML in command-line mode
-goroot=$GOROOT
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index 872b0dc1e..577432113 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -84,15 +84,11 @@ var (
cmdHandler docServer
pkgHandler docServer
- // which code 'Notes' to show
- notes = flag.String("notes", "BUG", "comma separated list of Note markers as per pkg:go/doc")
- // list of 'Notes' to show
- notesToShow []string
+ // source code notes
+ notes = flag.String("notes", "BUG", "regular expression matching note markers to show")
)
func initHandlers() {
- notesToShow = strings.Split(*notes, ",")
-
fileServer = http.FileServer(&httpFS{fs})
cmdHandler = docServer{"/cmd/", "/src/cmd"}
pkgHandler = docServer{"/pkg/", "/src/pkg"}
@@ -911,12 +907,12 @@ type PageInfo struct {
Err error // error or nil
// package info
- FSet *token.FileSet // nil if no package documentation
- PDoc *doc.Package // nil if no package documentation
- Examples []*doc.Example // nil if no example code
- Notes map[string][]string // nil if no package Notes
- PAst *ast.File // nil if no AST with package exports
- IsMain bool // true for package main
+ FSet *token.FileSet // nil if no package documentation
+ PDoc *doc.Package // nil if no package documentation
+ Examples []*doc.Example // nil if no example code
+ Notes map[string][]*doc.Note // nil if no package Notes
+ PAst *ast.File // nil if no AST with package exports
+ IsMain bool // true for package main
// directory info
Dirs *DirList // nil if no directory information
@@ -1100,10 +1096,15 @@ func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) (inf
// collect any notes that we want to show
if info.PDoc.Notes != nil {
- info.Notes = make(map[string][]string)
- for _, m := range notesToShow {
- if n := info.PDoc.Notes[m]; n != nil {
- info.Notes[m] = n
+ // could regexp.Compile only once per godoc, but probably not worth it
+ if rx, err := regexp.Compile(*notes); err == nil {
+ for m, n := range info.PDoc.Notes {
+ if rx.MatchString(m) {
+ if info.Notes == nil {
+ info.Notes = make(map[string][]*doc.Note)
+ }
+ info.Notes[m] = n
+ }
}
}
}
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 6c6b1be43..b70d4636c 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -33,6 +33,7 @@
#include "l.h"
#include "../ld/lib.h"
#include "../ld/elf.h"
+#include "../ld/macho.h"
#include "../ld/pe.h"
#include "../../pkg/runtime/mgc0.h"
@@ -135,11 +136,7 @@ addrel(Sym *s)
s->maxr = 4;
else
s->maxr <<= 1;
- s->r = realloc(s->r, s->maxr*sizeof s->r[0]);
- if(s->r == 0) {
- diag("out of memory");
- errorexit();
- }
+ s->r = erealloc(s->r, s->maxr*sizeof s->r[0]);
memset(s->r+s->nr, 0, (s->maxr-s->nr)*sizeof s->r[0]);
}
return &s->r[s->nr++];
@@ -158,6 +155,7 @@ relocsym(Sym *s)
cursym = s;
memset(&p, 0, sizeof p);
for(r=s->r; r<s->r+s->nr; r++) {
+ r->done = 1;
off = r->off;
siz = r->siz;
if(off < 0 || off+siz > s->np) {
@@ -180,35 +178,72 @@ relocsym(Sym *s)
switch(r->type) {
default:
o = 0;
- if(isobj || archreloc(r, s, &o) < 0)
+ if(linkmode == LinkExternal || archreloc(r, s, &o) < 0)
diag("unknown reloc %d", r->type);
break;
case D_ADDR:
- o = symaddr(r->sym) + r->add;
- if(isobj && r->sym->type != SCONST) {
- if(thechar == '6')
- o = 0;
- else {
- // set up addend for eventual relocation via outer symbol
- rs = r->sym;
- while(rs->outer != nil)
- rs = rs->outer;
- o -= symaddr(rs);
+ if(linkmode == LinkExternal && r->sym->type != SCONST) {
+ r->done = 0;
+
+ // set up addend for eventual relocation via outer symbol.
+ rs = r->sym;
+ r->xadd = r->add;
+ while(rs->outer != nil) {
+ r->xadd += symaddr(rs) - symaddr(rs->outer);
+ rs = rs->outer;
+ }
+ if(rs->type != SHOSTOBJ && rs->sect == nil)
+ diag("missing section for %s", rs->name);
+ r->xsym = rs;
+
+ o = r->xadd;
+ if(iself) {
+ if(thechar == '6')
+ o = 0;
+ } else if(HEADTYPE == Hdarwin) {
+ if(rs->type != SHOSTOBJ)
+ o += symaddr(rs);
+ } else {
+ diag("unhandled pcrel relocation for %s", headtype);
}
+ break;
}
+ o = symaddr(r->sym) + r->add;
break;
case D_PCREL:
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
+ if(linkmode == LinkExternal && r->sym && r->sym->type != SCONST && r->sym->sect != cursym->sect) {
+ r->done = 0;
+
+ // set up addend for eventual relocation via outer symbol.
+ rs = r->sym;
+ r->xadd = r->add;
+ while(rs->outer != nil) {
+ r->xadd += symaddr(rs) - symaddr(rs->outer);
+ rs = rs->outer;
+ }
+ r->xadd -= r->siz; // relative to address after the relocated chunk
+ if(rs->type != SHOSTOBJ && rs->sect == nil)
+ diag("missing section for %s", rs->name);
+ r->xsym = rs;
+
+ o = r->xadd;
+ if(iself) {
+ if(thechar == '6')
+ o = 0;
+ } else if(HEADTYPE == Hdarwin) {
+ if(rs->type != SHOSTOBJ)
+ o += symaddr(rs) - rs->sect->vaddr;
+ o -= r->off; // WTF?
+ } else {
+ diag("unhandled pcrel relocation for %s", headtype);
+ }
+ break;
+ }
o = 0;
if(r->sym)
o += symaddr(r->sym);
o += r->add - (s->value + r->off + r->siz);
- if(isobj && r->sym->type != SCONST) {
- if(thechar == '6')
- o = 0;
- else
- o = r->add - r->siz;
- }
break;
case D_SIZE:
o = r->sym->size + r->add;
@@ -300,7 +335,7 @@ dynrelocsym(Sym *s)
for(r=s->r; r<s->r+s->nr; r++) {
if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256)
adddynrel(s, r);
- if(flag_shared && r->sym != S && (r->sym->dynimpname == nil || r->sym->dynexport) && r->type == D_ADDR
+ if(flag_shared && r->sym != S && s->type != SDYNIMPORT && r->type == D_ADDR
&& (s == got || s->type == SDATA || s->type == SGOSTRING || s->type == STYPE || s->type == SRODATA)) {
// Create address based RELATIVE relocation
adddynrela(rel, s, r);
@@ -342,11 +377,7 @@ symgrow(Sym *s, int32 siz)
s->maxp = 8;
while(s->maxp < siz)
s->maxp <<= 1;
- s->p = realloc(s->p, s->maxp);
- if(s->p == nil) {
- diag("out of memory");
- errorexit();
- }
+ s->p = erealloc(s->p, s->maxp);
memset(s->p+s->np, 0, s->maxp-s->np);
}
s->np = siz;
@@ -560,8 +591,10 @@ void
datblk(int32 addr, int32 size)
{
Sym *sym;
- int32 eaddr;
+ int32 i, eaddr;
uchar *p, *ep;
+ char *typ, *rsname;
+ Reloc *r;
if(debug['a'])
Bprint(&bso, "datblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos());
@@ -581,23 +614,46 @@ datblk(int32 addr, int32 size)
if(sym->value >= eaddr)
break;
if(addr < sym->value) {
- Bprint(&bso, "%-20s %.8ux| 00 ...\n", "(pre-pad)", addr);
+ Bprint(&bso, "\t%.8ux| 00 ...\n", addr);
addr = sym->value;
}
- Bprint(&bso, "%-20s %.8ux|", sym->name, (uint)addr);
+ Bprint(&bso, "%s\n\t%.8ux|", sym->name, (uint)addr);
p = sym->p;
ep = p + sym->np;
- while(p < ep)
+ while(p < ep) {
+ if(p > sym->p && (int)(p-sym->p)%16 == 0)
+ Bprint(&bso, "\n\t%.8ux|", (uint)(addr+(p-sym->p)));
Bprint(&bso, " %.2ux", *p++);
+ }
addr += sym->np;
for(; addr < sym->value+sym->size; addr++)
Bprint(&bso, " %.2ux", 0);
Bprint(&bso, "\n");
+
+ if(linkmode == LinkExternal) {
+ for(i=0; i<sym->nr; i++) {
+ r = &sym->r[i];
+ rsname = "";
+ if(r->sym)
+ rsname = r->sym->name;
+ typ = "?";
+ switch(r->type) {
+ case D_ADDR:
+ typ = "addr";
+ break;
+ case D_PCREL:
+ typ = "pcrel";
+ break;
+ }
+ Bprint(&bso, "\treloc %.8ux/%d %s %s+%#llx [%#llx]\n",
+ (uint)(sym->value+r->off), r->siz, typ, rsname, r->add, r->sym->value+r->add);
+ }
+ }
}
if(addr < eaddr)
- Bprint(&bso, "%-20s %.8ux| 00 ...\n", "(post-pad)", (uint)addr);
- Bprint(&bso, "%-20s %.8ux|\n", "", (uint)eaddr);
+ Bprint(&bso, "\t%.8ux| 00 ...\n", (uint)addr);
+ Bprint(&bso, "\t%.8ux|\n", (uint)eaddr);
}
void
@@ -883,36 +939,41 @@ dosymtype(void)
}
static int32
-alignsymsize(int32 s)
+symalign(Sym *s)
{
- if(s >= 8)
- s = rnd(s, 8);
- else if(s >= PtrSize)
- s = rnd(s, PtrSize);
- else if(s > 2)
- s = rnd(s, 4);
- return s;
-}
+ int32 align;
+
+ if(s->align != 0)
+ return s->align;
+ align = MaxAlign;
+ while(align > s->size && align > 1)
+ align >>= 1;
+ if(align < s->align)
+ align = s->align;
+ return align;
+}
+
static int32
aligndatsize(int32 datsize, Sym *s)
{
- int32 t;
+ return rnd(datsize, symalign(s));
+}
- if(s->align != 0) {
- datsize = rnd(datsize, s->align);
- } else {
- t = alignsymsize(s->size);
- if(t & 1) {
- ;
- } else if(t & 2)
- datsize = rnd(datsize, 2);
- else if(t & 4)
- datsize = rnd(datsize, 4);
- else
- datsize = rnd(datsize, 8);
+// maxalign returns the maximum required alignment for
+// the list of symbols s; the list stops when s->type exceeds type.
+static int32
+maxalign(Sym *s, int type)
+{
+ int32 align, max;
+
+ max = 0;
+ for(; s != S && s->type <= type; s = s->next) {
+ align = symalign(s);
+ if(max < align)
+ max = align;
}
- return datsize;
+ return max;
}
static void
@@ -946,7 +1007,7 @@ gcaddsym(Sym *gc, Sym *s, int32 off)
void
dodata(void)
{
- int32 t, datsize;
+ int32 n, datsize;
Section *sect;
Sym *s, *last, **l;
Sym *gcdata1, *gcbss1;
@@ -956,11 +1017,11 @@ dodata(void)
Bflush(&bso);
// define garbage collection symbols
- gcdata1 = lookup("gcdata1", 0);
- gcdata1->type = SGCDATA;
+ gcdata1 = lookup("gcdata", 0);
+ gcdata1->type = STYPE;
gcdata1->reachable = 1;
- gcbss1 = lookup("gcbss1", 0);
- gcbss1->type = SGCBSS;
+ gcbss1 = lookup("gcbss", 0);
+ gcbss1->type = STYPE;
gcbss1->reachable = 1;
// size of .data and .bss section. the zero value is later replaced by the actual size of the section.
@@ -995,7 +1056,11 @@ dodata(void)
* to assign addresses, record all the necessary
* dynamic relocations. these will grow the relocation
* symbol, which is itself data.
+ *
+ * on darwin, we need the symbol table numbers for dynreloc.
*/
+ if(HEADTYPE == Hdarwin)
+ machosymorder();
dynreloc();
/* some symbols may no longer belong in datap (Mach-O) */
@@ -1034,52 +1099,54 @@ dodata(void)
datsize = 0;
for(; s != nil && s->type < SNOPTRDATA; s = s->next) {
sect = addsection(&segdata, s->name, 06);
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
+ sect->align = symalign(s);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
s->sect = sect;
s->type = SDATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
sect->len = datsize - sect->vaddr;
}
/* pointer-free data */
sect = addsection(&segdata, ".noptrdata", 06);
+ sect->align = maxalign(s, SDATARELRO-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("noptrdata", 0)->sect = sect;
lookup("enoptrdata", 0)->sect = sect;
for(; s != nil && s->type < SDATARELRO; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SDATA;
- t = alignsymsize(s->size);
- datsize = aligndatsize(datsize, s);
s->value = datsize;
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* dynamic relocated rodata */
if(flag_shared) {
sect = addsection(&segdata, ".data.rel.ro", 06);
+ sect->align = maxalign(s, SDATARELRO);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("datarelro", 0)->sect = sect;
lookup("edatarelro", 0)->sect = sect;
for(; s != nil && s->type == SDATARELRO; s = s->next) {
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SDATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
}
/* data */
sect = addsection(&segdata, ".data", 06);
+ sect->align = maxalign(s, SBSS-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("data", 0)->sect = sect;
lookup("edata", 0)->sect = sect;
@@ -1090,39 +1157,39 @@ dodata(void)
}
s->sect = sect;
s->type = SDATA;
- t = alignsymsize(s->size);
datsize = aligndatsize(datsize, s);
s->value = datsize;
gcaddsym(gcdata1, s, datsize - sect->vaddr); // gc
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
adduintxx(gcdata1, GC_END, PtrSize);
setuintxx(gcdata1, 0, sect->len, PtrSize);
/* bss */
sect = addsection(&segdata, ".bss", 06);
+ sect->align = maxalign(s, SNOPTRBSS-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("bss", 0)->sect = sect;
lookup("ebss", 0)->sect = sect;
for(; s != nil && s->type < SNOPTRBSS; s = s->next) {
s->sect = sect;
- t = alignsymsize(s->size);
datsize = aligndatsize(datsize, s);
s->value = datsize;
gcaddsym(gcbss1, s, datsize - sect->vaddr); // gc
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
adduintxx(gcbss1, GC_END, PtrSize);
setuintxx(gcbss1, 0, sect->len, PtrSize);
/* pointer-free bss */
sect = addsection(&segdata, ".noptrbss", 06);
+ sect->align = maxalign(s, SNOPTRBSS);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("noptrbss", 0)->sect = sect;
lookup("enoptrbss", 0)->sect = sect;
@@ -1131,117 +1198,101 @@ dodata(void)
cursym = s;
diag("unexpected symbol type %d", s->type);
}
- s->sect = sect;
- t = alignsymsize(s->size);
datsize = aligndatsize(datsize, s);
+ s->sect = sect;
s->value = datsize;
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
lookup("end", 0)->sect = sect;
/* we finished segdata, begin segtext */
+ s = datap;
+ datsize = 0;
/* read-only data */
sect = addsection(&segtext, ".rodata", 04);
+ sect->align = maxalign(s, STYPELINK-1);
sect->vaddr = 0;
lookup("rodata", 0)->sect = sect;
lookup("erodata", 0)->sect = sect;
datsize = 0;
- s = datap;
for(; s != nil && s->type < STYPELINK; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
s->type = SRODATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
- /* type */
+ /* typelink */
sect = addsection(&segtext, ".typelink", 04);
+ sect->align = maxalign(s, STYPELINK);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("typelink", 0)->sect = sect;
lookup("etypelink", 0)->sect = sect;
for(; s != nil && s->type == STYPELINK; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
-
- /* gcdata */
- sect = addsection(&segtext, ".gcdata", 04);
- sect->vaddr = datsize;
- lookup("gcdata", 0)->sect = sect;
- lookup("egcdata", 0)->sect = sect;
- for(; s != nil && s->type == SGCDATA; s = s->next) {
- s->sect = sect;
- s->type = SRODATA;
- s->value = datsize;
- datsize += s->size;
- }
- sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
-
- /* gcbss */
- sect = addsection(&segtext, ".gcbss", 04);
- sect->vaddr = datsize;
- lookup("gcbss", 0)->sect = sect;
- lookup("egcbss", 0)->sect = sect;
- for(; s != nil && s->type == SGCBSS; s = s->next) {
- s->sect = sect;
- s->type = SRODATA;
- s->value = datsize;
- datsize += s->size;
- }
- sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* gosymtab */
sect = addsection(&segtext, ".gosymtab", 04);
+ sect->align = maxalign(s, SPCLNTAB-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("symtab", 0)->sect = sect;
lookup("esymtab", 0)->sect = sect;
for(; s != nil && s->type < SPCLNTAB; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* gopclntab */
sect = addsection(&segtext, ".gopclntab", 04);
+ sect->align = maxalign(s, SELFROSECT-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("pclntab", 0)->sect = sect;
lookup("epclntab", 0)->sect = sect;
for(; s != nil && s->type < SELFROSECT; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
- /* read-only ELF sections */
+ /* read-only ELF, Mach-O sections */
for(; s != nil && s->type < SELFSECT; s = s->next) {
sect = addsection(&segtext, s->name, 04);
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
+ sect->align = symalign(s);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
sect->len = datsize - sect->vaddr;
}
+
+ /* number the sections */
+ n = 1;
+ for(sect = segtext.sect; sect != nil; sect = sect->next)
+ sect->extnum = n++;
+ for(sect = segdata.sect; sect != nil; sect = sect->next)
+ sect->extnum = n++;
}
// assign addresses to text
@@ -1259,6 +1310,7 @@ textaddress(void)
// Could parallelize, by assigning to text
// and then letting threads copy down, but probably not worth it.
sect = segtext.sect;
+ sect->align = FuncAlign;
lookup("text", 0)->sect = sect;
lookup("etext", 0)->sect = sect;
va = INITTEXT;
@@ -1282,11 +1334,6 @@ textaddress(void)
}
va += sym->size;
}
-
- // Align end of code so that rodata starts aligned.
- // 128 bytes is likely overkill but definitely cheap.
- va = rnd(va, 128);
-
sect->len = va - sect->vaddr;
}
@@ -1295,17 +1342,19 @@ void
address(void)
{
Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss, *datarelro;
- Section *gcdata, *gcbss, *typelink;
+ Section *typelink;
Sym *sym, *sub;
uvlong va;
+ vlong vlen;
va = INITTEXT;
segtext.rwx = 05;
segtext.vaddr = va;
segtext.fileoff = HEADR;
for(s=segtext.sect; s != nil; s=s->next) {
+ va = rnd(va, s->align);
s->vaddr = va;
- va += rnd(s->len, PtrSize);
+ va += s->len;
}
segtext.len = va - INITTEXT;
segtext.filelen = segtext.len;
@@ -1326,9 +1375,11 @@ address(void)
noptrbss = nil;
datarelro = nil;
for(s=segdata.sect; s != nil; s=s->next) {
+ vlen = s->len;
+ if(s->next)
+ vlen = s->next->vaddr - s->vaddr;
s->vaddr = va;
- va += s->len;
- segdata.filelen += s->len;
+ va += vlen;
segdata.len = va - segdata.vaddr;
if(strcmp(s->name, ".data") == 0)
data = s;
@@ -1341,14 +1392,12 @@ address(void)
if(strcmp(s->name, ".data.rel.ro") == 0)
datarelro = s;
}
- segdata.filelen -= bss->len + noptrbss->len; // deduct .bss
+ segdata.filelen = bss->vaddr - segdata.vaddr;
text = segtext.sect;
rodata = text->next;
typelink = rodata->next;
- gcdata = typelink->next;
- gcbss = gcdata->next;
- symtab = gcbss->next;
+ symtab = typelink->next;
pclntab = symtab->next;
for(sym = datap; sym != nil; sym = sym->next) {
@@ -1371,10 +1420,15 @@ address(void)
xdefine("datarelro", SRODATA, datarelro->vaddr);
xdefine("edatarelro", SRODATA, datarelro->vaddr + datarelro->len);
}
- xdefine("gcdata", SGCDATA, gcdata->vaddr);
- xdefine("egcdata", SGCDATA, gcdata->vaddr + gcdata->len);
- xdefine("gcbss", SGCBSS, gcbss->vaddr);
- xdefine("egcbss", SGCBSS, gcbss->vaddr + gcbss->len);
+
+ sym = lookup("gcdata", 0);
+ xdefine("egcdata", STYPE, symaddr(sym) + sym->size);
+ lookup("egcdata", 0)->sect = sym->sect;
+
+ sym = lookup("gcbss", 0);
+ xdefine("egcbss", STYPE, symaddr(sym) + sym->size);
+ lookup("egcbss", 0)->sect = sym->sect;
+
xdefine("symtab", SRODATA, symtab->vaddr);
xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
xdefine("pclntab", SRODATA, pclntab->vaddr);
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index d6a357e49..4bf788e64 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -41,9 +41,13 @@ static vlong arangeso;
static vlong arangessize;
static vlong gdbscripto;
static vlong gdbscriptsize;
+static vlong inforeloco;
+static vlong inforelocsize;
static char gdbscript[1024];
+static Sym *dsym;
+
/*
* Basic I/O
*/
@@ -150,6 +154,7 @@ enum
DW_ABRV_IFACETYPE,
DW_ABRV_MAPTYPE,
DW_ABRV_PTRTYPE,
+ DW_ABRV_BARE_PTRTYPE, // only for void*, no DW_AT_type attr to please gdb 6.
DW_ABRV_SLICETYPE,
DW_ABRV_STRINGTYPE,
DW_ABRV_STRUCTTYPE,
@@ -303,6 +308,12 @@ static struct DWAbbrev {
DW_AT_type, DW_FORM_ref_addr,
0, 0
},
+ /* BARE_PTRTYPE */
+ {
+ DW_TAG_pointer_type, DW_CHILDREN_no,
+ DW_AT_name, DW_FORM_string,
+ 0, 0
+ },
/* SLICETYPE */
{
@@ -485,26 +496,43 @@ mkindex(DWDie *die)
die->hash = mal(HASHSIZE * sizeof(DWDie*));
}
+static DWDie*
+walktypedef(DWDie *die)
+{
+ DWAttr *attr;
+
+ // Resolve typedef if present.
+ if (die->abbrev == DW_ABRV_TYPEDECL) {
+ for (attr = die->attr; attr; attr = attr->link) {
+ if (attr->atr == DW_AT_type && attr->cls == DW_CLS_REFERENCE && attr->data != nil) {
+ return (DWDie*)attr->data;
+ }
+ }
+ }
+ return die;
+}
+
// Find child by AT_name using hashtable if available or linear scan
// if not.
static DWDie*
find(DWDie *die, char* name)
{
- DWDie *a, *b;
+ DWDie *a, *b, *die2;
int h;
+top:
if (die->hash == nil) {
for (a = die->child; a != nil; a = a->link)
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
return a;
- return nil;
+ goto notfound;
}
h = hashstr(name);
a = die->hash[h];
if (a == nil)
- return nil;
+ goto notfound;
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
@@ -522,6 +550,14 @@ find(DWDie *die, char* name)
a = b;
b = b->hlink;
}
+
+notfound:
+ die2 = walktypedef(die);
+ if(die2 != die) {
+ die = die2;
+ goto top;
+ }
+
return nil;
}
@@ -531,7 +567,7 @@ find_or_diag(DWDie *die, char* name)
DWDie *r;
r = find(die, name);
if (r == nil) {
- diag("dwarf find: %s has no %s", getattr(die, DW_AT_name)->data, name);
+ diag("dwarf find: %s %p has no %s", getattr(die, DW_AT_name)->data, die, name);
errorexit();
}
return r;
@@ -548,14 +584,33 @@ newrefattr(DWDie *die, uint8 attr, DWDie* ref)
static int fwdcount;
static void
-putattr(int form, int cls, vlong value, char *data)
+putattr(int abbrev, int form, int cls, vlong value, char *data)
{
+ Reloc *r;
+
switch(form) {
case DW_FORM_addr: // address
addrput(value);
break;
case DW_FORM_block1: // block
+ if(cls == DW_CLS_ADDRESS) {
+ cput(1+PtrSize);
+ cput(DW_OP_addr);
+ if(linkmode == LinkExternal) {
+ r = addrel(dsym);
+ r->sym = (Sym*)data;
+ r->xsym = r->sym;
+ r->off = cpos() - infoo;
+ r->siz = PtrSize;
+ r->type = D_ADDR;
+ r->add = value - r->sym->value;
+ r->xadd = r->add;
+ value = r->add;
+ }
+ addrput(value);
+ break;
+ }
value &= 0xff;
cput(value);
while(value--)
@@ -615,13 +670,23 @@ putattr(int form, int cls, vlong value, char *data)
break;
case DW_FORM_ref_addr: // reference to a DIE in the .info section
+ // In DWARF 2 (which is what we claim to generate),
+ // the ref_addr is the same size as a normal address.
+ // In DWARF 3 it is always 32 bits, unless emitting a large
+ // (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
if (data == nil) {
- diag("dwarf: null reference");
- LPUT(0); // invalid dwarf, gdb will complain.
+ diag("dwarf: null reference in %d", abbrev);
+ if(PtrSize == 8)
+ VPUT(0); // invalid dwarf, gdb will complain.
+ else
+ LPUT(0); // invalid dwarf, gdb will complain.
} else {
if (((DWDie*)data)->offs == 0)
fwdcount++;
- LPUT(((DWDie*)data)->offs);
+ if(PtrSize == 8)
+ VPUT(((DWDie*)data)->offs);
+ else
+ LPUT(((DWDie*)data)->offs);
}
break;
@@ -654,12 +719,12 @@ putattrs(int abbrev, DWAttr* attr)
for(af = abbrevs[abbrev].attr; af->attr; af++)
if (attrs[af->attr])
- putattr(af->form,
+ putattr(abbrev, af->form,
attrs[af->attr]->cls,
attrs[af->attr]->value,
attrs[af->attr]->data);
else
- putattr(af->form, 0, 0, 0);
+ putattr(abbrev, af->form, 0, 0, nil);
}
static void putdie(DWDie* die);
@@ -729,16 +794,9 @@ newmemberoffsetattr(DWDie *die, int32 offs)
// GDB doesn't like DW_FORM_addr for DW_AT_location, so emit a
// location expression that evals to a const.
static void
-newabslocexprattr(DWDie *die, vlong addr)
+newabslocexprattr(DWDie *die, vlong addr, Sym *sym)
{
- char block[10];
- int i;
-
- i = 0;
- block[i++] = DW_OP_constu;
- i += uleb128enc(addr, block+i);
- newattr(die, DW_AT_location, DW_CLS_BLOCK, i, mal(i));
- memmove(die->attr->data, block, i);
+ newattr(die, DW_AT_location, DW_CLS_ADDRESS, addr, (char*)sym);
}
@@ -766,6 +824,31 @@ lookup_or_diag(char *n)
return s;
}
+static void
+dotypedef(DWDie *parent, char *name, DWDie *def)
+{
+ DWDie *die;
+
+ // Only emit typedefs for real names.
+ if(strncmp(name, "map[", 4) == 0)
+ return;
+ if(strncmp(name, "struct {", 8) == 0)
+ return;
+ if(strncmp(name, "chan ", 5) == 0)
+ return;
+ if(*name == '[' || *name == '*')
+ return;
+ if(def == nil)
+ diag("dwarf: bad def in dotypedef");
+
+ // The typedef entry must be created after the def,
+ // so that future lookups will find the typedef instead
+ // of the real definition. This hooks the typedef into any
+ // circular definition loops, so that gdb can understand them.
+ die = newdie(parent, DW_ABRV_TYPEDECL, name);
+ newrefattr(die, DW_AT_type, def);
+}
+
// Define gotype, for composite ones recurse into constituents.
static DWDie*
defgotype(Sym *gotype)
@@ -840,6 +923,7 @@ defgotype(Sym *gotype)
case KindArray:
die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name);
+ dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s));
@@ -857,6 +941,7 @@ defgotype(Sym *gotype)
case KindFunc:
die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name);
+ dotypedef(&dwtypes, name, die);
newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "void"));
nfields = decodetype_funcincount(gotype);
for (i = 0; i < nfields; i++) {
@@ -876,6 +961,7 @@ defgotype(Sym *gotype)
case KindInterface:
die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name);
+ dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
nfields = decodetype_ifacemethodcount(gotype);
if (nfields == 0)
@@ -895,12 +981,14 @@ defgotype(Sym *gotype)
case KindPtr:
die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name);
+ dotypedef(&dwtypes, name, die);
s = decodetype_ptrelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s));
break;
case KindSlice:
die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name);
+ dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
@@ -913,6 +1001,7 @@ defgotype(Sym *gotype)
case KindStruct:
die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name);
+ dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
nfields = decodetype_structfieldcount(gotype);
for (i = 0; i < nfields; i++) {
@@ -927,8 +1016,7 @@ defgotype(Sym *gotype)
break;
case KindUnsafePointer:
- die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name);
- newrefattr(die, DW_AT_type, find(&dwtypes, "void"));
+ die = newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, name);
break;
default:
@@ -998,7 +1086,7 @@ synthesizestringtypes(DWDie* die)
{
DWDie *prototype;
- prototype = defgotype(lookup_or_diag("type.runtime._string"));
+ prototype = walktypedef(defgotype(lookup_or_diag("type.runtime._string")));
if (prototype == nil)
return;
@@ -1014,7 +1102,7 @@ synthesizeslicetypes(DWDie *die)
{
DWDie *prototype, *elem;
- prototype = defgotype(lookup_or_diag("type.runtime.slice"));
+ prototype = walktypedef(defgotype(lookup_or_diag("type.runtime.slice")));
if (prototype == nil)
return;
@@ -1043,33 +1131,17 @@ mkinternaltypename(char *base, char *arg1, char *arg2)
}
-// synthesizemaptypes is way too closely married to runtime/hashmap.c
-enum {
- MaxValsize = 256 - 64
-};
-
static void
synthesizemaptypes(DWDie *die)
{
- DWDie *hash, *hash_subtable, *hash_entry,
- *dwh, *dwhs, *dwhe, *dwhash, *keytype, *valtype, *fld;
- int hashsize, keysize, valsize, datsize, valsize_in_hash, datavo;
- DWAttr *a;
+ DWDie *hash, *dwh, *keytype, *valtype;
hash = defgotype(lookup_or_diag("type.runtime.hmap"));
- hash_subtable = defgotype(lookup_or_diag("type.runtime.hash_subtable"));
- hash_entry = defgotype(lookup_or_diag("type.runtime.hash_entry"));
- if (hash == nil || hash_subtable == nil || hash_entry == nil)
+ if (hash == nil)
return;
- dwhash = (DWDie*)getattr(find_or_diag(hash_entry, "hash"), DW_AT_type)->data;
- if (dwhash == nil)
- return;
-
- hashsize = getattr(dwhash, DW_AT_byte_size)->value;
-
for (; die != nil; die = die->link) {
if (die->abbrev != DW_ABRV_MAPTYPE)
continue;
@@ -1077,63 +1149,12 @@ synthesizemaptypes(DWDie *die)
keytype = (DWDie*) getattr(die, DW_AT_internal_key_type)->data;
valtype = (DWDie*) getattr(die, DW_AT_internal_val_type)->data;
- a = getattr(keytype, DW_AT_byte_size);
- keysize = a ? a->value : PtrSize; // We don't store size with Pointers
-
- a = getattr(valtype, DW_AT_byte_size);
- valsize = a ? a->value : PtrSize;
-
- // This is what happens in hash_init and makemap_c
- valsize_in_hash = valsize;
- if (valsize > MaxValsize)
- valsize_in_hash = PtrSize;
- datavo = keysize;
- if (valsize_in_hash >= PtrSize)
- datavo = rnd(keysize, PtrSize);
- datsize = datavo + valsize_in_hash;
- if (datsize < PtrSize)
- datsize = PtrSize;
- datsize = rnd(datsize, PtrSize);
-
- // Construct struct hash_entry<K,V>
- dwhe = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("hash_entry",
- getattr(keytype, DW_AT_name)->data,
- getattr(valtype, DW_AT_name)->data));
-
- fld = newdie(dwhe, DW_ABRV_STRUCTFIELD, "hash");
- newrefattr(fld, DW_AT_type, dwhash);
- newmemberoffsetattr(fld, 0);
-
- fld = newdie(dwhe, DW_ABRV_STRUCTFIELD, "key");
- newrefattr(fld, DW_AT_type, keytype);
- newmemberoffsetattr(fld, hashsize);
-
- fld = newdie(dwhe, DW_ABRV_STRUCTFIELD, "val");
- if (valsize > MaxValsize)
- valtype = defptrto(valtype);
- newrefattr(fld, DW_AT_type, valtype);
- newmemberoffsetattr(fld, hashsize + datavo);
- newattr(dwhe, DW_AT_byte_size, DW_CLS_CONSTANT, hashsize + datsize, nil);
-
- // Construct hash_subtable<hash_entry<K,V>>
- dwhs = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("hash_subtable",
- getattr(keytype, DW_AT_name)->data,
- getattr(valtype, DW_AT_name)->data));
- copychildren(dwhs, hash_subtable);
- substitutetype(dwhs, "last", defptrto(dwhe));
- substitutetype(dwhs, "entry", dwhe); // todo: []hash_entry with dynamic size
- newattr(dwhs, DW_AT_byte_size, DW_CLS_CONSTANT,
- getattr(hash_subtable, DW_AT_byte_size)->value, nil);
-
// Construct hash<K,V>
dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
mkinternaltypename("hash",
getattr(keytype, DW_AT_name)->data,
getattr(valtype, DW_AT_name)->data));
copychildren(dwh, hash);
- substitutetype(dwh, "st", defptrto(dwhs));
newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT,
getattr(hash, DW_AT_byte_size)->value, nil);
@@ -1149,9 +1170,9 @@ synthesizechantypes(DWDie *die)
DWAttr *a;
int elemsize, sudogsize;
- sudog = defgotype(lookup_or_diag("type.runtime.sudog"));
- waitq = defgotype(lookup_or_diag("type.runtime.waitq"));
- hchan = defgotype(lookup_or_diag("type.runtime.hchan"));
+ sudog = walktypedef(defgotype(lookup_or_diag("type.runtime.sudog")));
+ waitq = walktypedef(defgotype(lookup_or_diag("type.runtime.waitq")));
+ hchan = walktypedef(defgotype(lookup_or_diag("type.runtime.hchan")));
if (sudog == nil || waitq == nil || hchan == nil)
return;
@@ -1220,7 +1241,7 @@ defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype)
case 'D':
case 'B':
dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s);
- newabslocexprattr(dv, v);
+ newabslocexprattr(dv, v, sym);
if (ver == 0)
newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0);
// fallthrough
@@ -1260,7 +1281,7 @@ dwarfaddfrag(int n, char *frag)
if (n >= ftabsize) {
s = ftabsize;
ftabsize = 1 + n + (n >> 2);
- ftab = realloc(ftab, ftabsize * sizeof(ftab[0]));
+ ftab = erealloc(ftab, ftabsize * sizeof(ftab[0]));
memset(ftab + s, 0, (ftabsize - s) * sizeof(ftab[0]));
}
@@ -1342,7 +1363,7 @@ addhistfile(char *zentry)
if (histfilesize == histfilecap) {
histfilecap = 2 * histfilecap + 2;
- histfile = realloc(histfile, histfilecap * sizeof(char*));
+ histfile = erealloc(histfile, histfilecap * sizeof(char*));
}
if (histfilesize == 0)
histfile[histfilesize++] = "<eof>";
@@ -1412,7 +1433,7 @@ checknesting(void)
includestacksize += 1;
includestacksize <<= 2;
// print("checknesting: growing to %d\n", includestacksize);
- includestack = realloc(includestack, includestacksize * sizeof *includestack);
+ includestack = erealloc(includestack, includestacksize * sizeof *includestack);
}
}
@@ -1581,12 +1602,12 @@ mkvarname(char* name, int da)
// flush previous compilation unit.
static void
-flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
+flushunit(DWDie *dwinfo, vlong pc, Sym *pcsym, vlong unitstart, int32 header_length)
{
vlong here;
if (dwinfo != nil && pc != 0) {
- newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, 0);
+ newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, (char*)pcsym);
}
if (unitstart >= 0) {
@@ -1597,7 +1618,7 @@ flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
here = cpos();
cseek(unitstart);
LPUT(here - unitstart - sizeof(int32)); // unit_length
- WPUT(3); // dwarf version
+ WPUT(2); // dwarf version
LPUT(header_length); // header length starting here
cseek(here);
}
@@ -1607,7 +1628,7 @@ static void
writelines(void)
{
Prog *q;
- Sym *s;
+ Sym *s, *epcs;
Auto *a;
vlong unitstart, headerend, offs;
vlong pc, epc, lc, llc, lline;
@@ -1622,6 +1643,7 @@ writelines(void)
headerend = -1;
pc = 0;
epc = 0;
+ epcs = S;
lc = 1;
llc = 1;
currfile = -1;
@@ -1637,7 +1659,7 @@ writelines(void)
// we're entering a new compilation unit
if (inithist(s->autom)) {
- flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
+ flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
unitstart = cpos();
if(debug['v'] > 1) {
@@ -1651,15 +1673,15 @@ writelines(void)
lang = guesslang(histfile[1]);
finddebugruntimepath();
- dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, strdup(histfile[1]));
+ dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, estrdup(histfile[1]));
newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT,lang, 0);
newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, unitstart - lineo, 0);
- newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, 0);
+ newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, (char*)s);
// Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf
LPUT(0); // unit_length (*), will be filled in by flushunit.
- WPUT(3); // dwarf version (appendix F)
+ WPUT(2); // dwarf version (appendix F)
LPUT(0); // header_length (*), filled in by flushunit.
// cpos == unitstart + 4 + 2 + 4
cput(1); // minimum_instruction_length
@@ -1683,6 +1705,7 @@ writelines(void)
pc = s->text->pc;
epc = pc;
+ epcs = s;
currfile = 1;
lc = 1;
llc = 1;
@@ -1701,9 +1724,9 @@ writelines(void)
}
dwfunc = newdie(dwinfo, DW_ABRV_FUNCTION, s->name);
- newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, 0);
+ newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, (char*)s);
epc = s->value + s->size;
- newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, 0);
+ newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, (char*)s);
if (s->version == 0)
newattr(dwfunc, DW_AT_external, DW_CLS_FLAG, 1, 0);
@@ -1785,7 +1808,7 @@ writelines(void)
dwfunc->hash = nil;
}
- flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
+ flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
linesize = cpos() - lineo;
}
@@ -1909,6 +1932,9 @@ writeinfo(void)
vlong unitstart, here;
fwdcount = 0;
+ if (dsym == S)
+ dsym = lookup(".dwarfinfo", 0);
+ dsym->nr = 0;
for (compunit = dwroot.child; compunit; compunit = compunit->link) {
unitstart = cpos();
@@ -1917,7 +1943,7 @@ writeinfo(void)
// Fields marked with (*) must be changed for 64-bit dwarf
// This must match COMPUNITHEADERSIZE above.
LPUT(0); // unit_length (*), will be filled in later.
- WPUT(3); // dwarf version (appendix F)
+ WPUT(2); // dwarf version (appendix F)
LPUT(0); // debug_abbrev_offset (*)
cput(PtrSize); // address_size
@@ -2057,6 +2083,27 @@ align(vlong size)
strnput("", rnd(size, PEFILEALIGN) - size);
}
+static vlong
+writeinforeloc(void)
+{
+ int i;
+ vlong start;
+ Reloc *r;
+
+ start = cpos();
+ for(r = dsym->r; r < dsym->r+dsym->nr; r++) {
+ if(iself)
+ i = elfreloc1(r, r->off);
+ else if(HEADTYPE == Hdarwin)
+ i = machoreloc1(r, r->off);
+ else
+ i = -1;
+ if(i < 0)
+ diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
+ }
+ return start;
+}
+
/*
* This is the main entry point for generating dwarf. After emitting
* the mandatory debug_abbrev section, it calls writelines() to set up
@@ -2085,8 +2132,7 @@ dwarfemitdebugsections(void)
// Some types that must exist to define other ones.
newdie(&dwtypes, DW_ABRV_NULLTYPE, "<unspecified>");
newdie(&dwtypes, DW_ABRV_NULLTYPE, "void");
- newrefattr(newdie(&dwtypes, DW_ABRV_PTRTYPE, "unsafe.Pointer"),
- DW_AT_type, find(&dwtypes, "void"));
+ newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer");
die = newdie(&dwtypes, DW_ABRV_BASETYPE, "uintptr"); // needed for array size
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, PtrSize, 0);
@@ -2157,6 +2203,10 @@ dwarfemitdebugsections(void)
gdbscripto = writegdbscript();
gdbscriptsize = cpos() - gdbscripto;
align(gdbscriptsize);
+
+ inforeloco = writeinforeloc();
+ inforelocsize = cpos() - inforeloco;
+ align(inforelocsize);
}
/*
@@ -2298,42 +2348,44 @@ dwarfaddmachoheaders(void)
ms->fileoffset = fakestart;
ms->filesize = abbrevo-fakestart;
- msect = newMachoSect(ms, "__debug_abbrev");
+ msect = newMachoSect(ms, "__debug_abbrev", "__DWARF");
msect->off = abbrevo;
msect->size = abbrevsize;
ms->filesize += msect->size;
- msect = newMachoSect(ms, "__debug_line");
+ msect = newMachoSect(ms, "__debug_line", "__DWARF");
msect->off = lineo;
msect->size = linesize;
ms->filesize += msect->size;
- msect = newMachoSect(ms, "__debug_frame");
+ msect = newMachoSect(ms, "__debug_frame", "__DWARF");
msect->off = frameo;
msect->size = framesize;
ms->filesize += msect->size;
- msect = newMachoSect(ms, "__debug_info");
+ msect = newMachoSect(ms, "__debug_info", "__DWARF");
msect->off = infoo;
msect->size = infosize;
+ msect->reloc = inforeloco;
+ msect->nreloc = inforelocsize / 8;
ms->filesize += msect->size;
if (pubnamessize > 0) {
- msect = newMachoSect(ms, "__debug_pubnames");
+ msect = newMachoSect(ms, "__debug_pubnames", "__DWARF");
msect->off = pubnameso;
msect->size = pubnamessize;
ms->filesize += msect->size;
}
if (pubtypessize > 0) {
- msect = newMachoSect(ms, "__debug_pubtypes");
+ msect = newMachoSect(ms, "__debug_pubtypes", "__DWARF");
msect->off = pubtypeso;
msect->size = pubtypessize;
ms->filesize += msect->size;
}
if (arangessize > 0) {
- msect = newMachoSect(ms, "__debug_aranges");
+ msect = newMachoSect(ms, "__debug_aranges", "__DWARF");
msect->off = arangeso;
msect->size = arangessize;
ms->filesize += msect->size;
@@ -2341,7 +2393,7 @@ dwarfaddmachoheaders(void)
// TODO(lvd) fix gdb/python to load MachO (16 char section name limit)
if (gdbscriptsize > 0) {
- msect = newMachoSect(ms, "__debug_gdb_scripts");
+ msect = newMachoSect(ms, "__debug_gdb_scripts", "__DWARF");
msect->off = gdbscripto;
msect->size = gdbscriptsize;
ms->filesize += msect->size;
diff --git a/src/cmd/ld/dwarf_defs.h b/src/cmd/ld/dwarf_defs.h
index eed143dff..93e99ff74 100644
--- a/src/cmd/ld/dwarf_defs.h
+++ b/src/cmd/ld/dwarf_defs.h
@@ -93,6 +93,7 @@ enum
DW_CLS_FLAG,
DW_CLS_PTR, // lineptr, loclistptr, macptr, rangelistptr
DW_CLS_REFERENCE,
+ DW_CLS_ADDRLOC,
DW_CLS_STRING
};
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index 630906653..f5cce9c52 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -605,9 +605,7 @@ elfdynhash(void)
if(sy->dynimpvers)
need[sy->dynid] = addelflib(&needlib, sy->dynimplib, sy->dynimpvers);
- name = sy->dynimpname;
- if(name == nil)
- name = sy->name;
+ name = sy->extname;
hc = elfhash((uchar*)name);
b = hc % nbucket;
@@ -760,9 +758,9 @@ elfshbits(Section *sect)
sh->flags |= SHF_EXECINSTR;
if(sect->rwx & 2)
sh->flags |= SHF_WRITE;
- if(!isobj)
+ if(linkmode != LinkExternal)
sh->addr = sect->vaddr;
- sh->addralign = PtrSize;
+ sh->addralign = sect->align;
sh->size = sect->len;
sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
@@ -807,10 +805,9 @@ elfshreloc(Section *sect)
void
elfrelocsect(Section *sect, Sym *first)
{
- Sym *sym, *rs;
+ Sym *sym;
int32 eaddr;
Reloc *r;
- int64 add;
// If main section is SHT_NOBITS, nothing to relocate.
// Also nothing to relocate in .shstrtab.
@@ -836,28 +833,15 @@ elfrelocsect(Section *sect, Sym *first)
cursym = sym;
for(r = sym->r; r < sym->r+sym->nr; r++) {
- // Ignore relocations handled by reloc already.
- switch(r->type) {
- case D_SIZE:
+ if(r->done)
+ continue;
+ if(r->xsym == nil) {
+ diag("missing xsym in relocation");
continue;
- case D_ADDR:
- case D_PCREL:
- if(r->sym->type == SCONST)
- continue;
- break;
- }
-
- add = r->add;
- rs = r->sym;
- while(rs->outer != nil) {
- add += rs->value - rs->outer->value;
- rs = rs->outer;
}
-
- if(rs->elfsym == 0)
- diag("reloc %d to non-elf symbol %s (rs=%s) %d", r->type, r->sym->name, rs->name, rs->type);
-
- if(elfreloc1(r, sym->value - sect->vaddr + r->off, rs->elfsym, add) < 0)
+ if(r->xsym->elfsym == 0)
+ diag("reloc %d to non-elf symbol %s (outer=%s) %d", r->type, r->sym->name, r->xsym->name, r->sym->type);
+ if(elfreloc1(r, sym->value+r->off - sect->vaddr) < 0)
diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
}
}
@@ -915,7 +899,7 @@ doelf(void)
addstring(shstrtab, ".gosymtab");
addstring(shstrtab, ".gopclntab");
- if(isobj) {
+ if(linkmode == LinkExternal) {
debug['s'] = 0;
debug['d'] = 1;
@@ -1147,7 +1131,7 @@ asmbelf(vlong symo)
resoff = ELFRESERVE;
pph = nil;
- if(isobj) {
+ if(linkmode == LinkExternal) {
/* skip program headers */
eh->phoff = 0;
eh->phentsize = 0;
@@ -1408,7 +1392,7 @@ elfobj:
for(sect=segdata.sect; sect!=nil; sect=sect->next)
elfshbits(sect);
- if(isobj) {
+ if(linkmode == LinkExternal) {
for(sect=segtext.sect; sect!=nil; sect=sect->next)
elfshreloc(sect);
for(sect=segdata.sect; sect!=nil; sect=sect->next)
@@ -1431,8 +1415,8 @@ elfobj:
sh->size = elfstrsize;
sh->addralign = 1;
- // TODO(rsc): Enable for isobj too, once we know it works.
- if(!isobj)
+ // TODO(rsc): Enable for linkmode == LinkExternal too, once we know it works.
+ if(linkmode != LinkExternal)
dwarfaddelfheaders();
}
@@ -1456,12 +1440,12 @@ elfobj:
if(flag_shared)
eh->type = ET_DYN;
- else if(isobj)
+ else if(linkmode == LinkExternal)
eh->type = ET_REL;
else
eh->type = ET_EXEC;
- if(!isobj)
+ if(linkmode != LinkExternal)
eh->entry = entryvalue();
eh->version = EV_CURRENT;
@@ -1478,7 +1462,7 @@ elfobj:
a += elfwriteshdrs();
if(!debug['d'])
a += elfwriteinterp();
- if(!isobj) {
+ if(linkmode != LinkExternal) {
if(HEADTYPE == Hnetbsd)
a += elfwritenetbsdsig();
if(HEADTYPE == Hopenbsd)
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index 3e22125b2..336fab4b4 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -1005,7 +1005,7 @@ extern char linuxdynld[];
extern char freebsddynld[];
extern char netbsddynld[];
extern char openbsddynld[];
-int elfreloc1(Reloc*, vlong off, int32 elfsym, vlong add);
+int elfreloc1(Reloc*, vlong sectoff);
EXTERN int elfstrsize;
EXTERN char* elfstrdat;
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index b2527b13e..f933cbba3 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -59,7 +59,7 @@ ilookup(char *name)
if(x->name[0] == name[0] && strcmp(x->name, name) == 0)
return x;
x = mal(sizeof *x);
- x->name = strdup(name);
+ x->name = estrdup(name);
x->hash = ihash[h];
ihash[h] = x;
nimport++;
@@ -71,8 +71,6 @@ static void loadcgo(char*, char*, char*, int);
static int parsemethod(char**, char*, char**);
static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**);
-static Sym **dynexp;
-
void
ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence)
{
@@ -205,14 +203,14 @@ loadpkgdata(char *file, char *pkg, char *data, int len)
char *p, *ep, *prefix, *name, *def;
Import *x;
- file = strdup(file);
+ file = estrdup(file);
p = data;
ep = data + len;
while(parsepkgdata(file, pkg, &p, ep, &prefix, &name, &def) > 0) {
x = ilookup(name);
if(x->prefix == nil) {
x->prefix = prefix;
- x->def = strdup(def);
+ x->def = estrdup(def);
x->file = file;
} else if(strcmp(x->prefix, prefix) != 0) {
fprint(2, "%s: conflicting definitions for %s\n", argv0, name);
@@ -244,7 +242,7 @@ expandpkg(char *t0, char *pkg)
n++;
if(n == 0)
- return strdup(t0);
+ return estrdup(t0);
// use malloc, not mal, so that caller can free
w0 = malloc(strlen(t0) + strlen(pkg)*n);
@@ -429,7 +427,7 @@ loadcgo(char *file, char *pkg, char *p, int n)
*next++ = '\0';
free(p0);
- p0 = strdup(p); // save for error message
+ p0 = estrdup(p); // save for error message
nf = tokenize(p, f, nelem(f));
if(strcmp(f[0], "cgo_import_dynamic") == 0) {
@@ -467,7 +465,7 @@ loadcgo(char *file, char *pkg, char *p, int n)
free(local);
if(s->type == 0 || s->type == SXREF) {
s->dynimplib = lib;
- s->dynimpname = remote;
+ s->extname = remote;
s->dynimpvers = q;
s->type = SDYNIMPORT;
havedynamic = 1;
@@ -478,16 +476,18 @@ loadcgo(char *file, char *pkg, char *p, int n)
if(strcmp(f[0], "cgo_import_static") == 0) {
if(nf != 2)
goto err;
- if(isobj) {
- local = f[1];
- s = lookup(local, 0);
- s->type = SHOSTOBJ;
- s->size = 0;
- }
+ local = f[1];
+ s = lookup(local, 0);
+ s->type = SHOSTOBJ;
+ s->size = 0;
continue;
}
- if(strcmp(f[0], "cgo_export") == 0) {
+ if(strcmp(f[0], "cgo_export_static") == 0 || strcmp(f[0], "cgo_export_dynamic") == 0) {
+ // TODO: Remove once we know Windows is okay.
+ if(strcmp(f[0], "cgo_export_static") == 0 && HEADTYPE == Hwindows)
+ continue;
+
if(nf < 2 || nf > 3)
goto err;
local = f[1];
@@ -497,17 +497,30 @@ loadcgo(char *file, char *pkg, char *p, int n)
remote = local;
local = expandpkg(local, pkg);
s = lookup(local, 0);
+
+ // export overrides import, for openbsd/cgo.
+ // see issue 4878.
if(s->dynimplib != nil) {
- fprint(2, "%s: symbol is both imported and exported: %s\n", argv0, local);
- nerrors++;
+ s->dynimplib = nil;
+ s->extname = nil;
+ s->dynimpvers = nil;
+ s->type = 0;
}
- s->dynimpname = remote;
- s->dynexport = 1;
-
- if(ndynexp%32 == 0)
- dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
- dynexp[ndynexp++] = s;
+ if(s->cgoexport == 0) {
+ if(strcmp(f[0], "cgo_export_static") == 0)
+ s->cgoexport |= CgoExportStatic;
+ else
+ s->cgoexport |= CgoExportDynamic;
+ s->extname = remote;
+ if(ndynexp%32 == 0)
+ dynexp = erealloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
+ dynexp[ndynexp++] = s;
+ } else if(strcmp(s->extname, remote) != 0) {
+ fprint(2, "%s: conflicting cgo_export directives: %s as %s and %s\n", argv0, s->name, s->extname, remote);
+ nerrors++;
+ return;
+ }
if(local != f[1])
free(local);
continue;
@@ -524,10 +537,19 @@ loadcgo(char *file, char *pkg, char *p, int n)
return;
}
free(interpreter);
- interpreter = strdup(f[1]);
+ interpreter = estrdup(f[1]);
}
continue;
}
+
+ if(strcmp(f[0], "cgo_ldflag") == 0) {
+ if(nf != 2)
+ goto err;
+ if(nldflag%32 == 0)
+ ldflag = erealloc(ldflag, (nldflag+32)*sizeof ldflag[0]);
+ ldflag[nldflag++] = estrdup(f[1]);
+ continue;
+ }
}
free(p0);
return;
@@ -751,6 +773,9 @@ addexport(void)
{
int i;
+ if(HEADTYPE == Hdarwin)
+ return;
+
for(i=0; i<ndynexp; i++)
adddynsym(dynexp[i]);
}
@@ -829,7 +854,7 @@ getpkg(char *path)
if(strcmp(p->path, path) == 0)
return p;
p = mal(sizeof *p);
- p->path = strdup(path);
+ p->path = estrdup(path);
p->next = phash[h];
phash[h] = p;
p->all = pkgall;
@@ -853,7 +878,7 @@ imported(char *pkg, char *import)
i->mimpby *= 2;
if(i->mimpby == 0)
i->mimpby = 16;
- i->impby = realloc(i->impby, i->mimpby*sizeof i->impby[0]);
+ i->impby = erealloc(i->impby, i->mimpby*sizeof i->impby[0]);
}
i->impby[i->nimpby++] = p;
free(pkg);
@@ -899,27 +924,17 @@ importcycles(void)
cycle(p);
}
-static int
-scmp(const void *p1, const void *p2)
-{
- Sym *s1, *s2;
-
- s1 = *(Sym**)p1;
- s2 = *(Sym**)p2;
- return strcmp(s1->dynimpname, s2->dynimpname);
-}
void
-sortdynexp(void)
+setlinkmode(char *arg)
{
- int i;
-
- // On Mac OS X Mountain Lion, we must sort exported symbols
- // So we sort them here and pre-allocate dynid for them
- // See http://golang.org/issue/4029
- if(HEADTYPE != Hdarwin)
- return;
- qsort(dynexp, ndynexp, sizeof dynexp[0], scmp);
- for(i=0; i<ndynexp; i++) {
- dynexp[i]->dynid = -i-100; // also known to [68]l/asm.c:^adddynsym
+ if(strcmp(arg, "internal") == 0)
+ linkmode = LinkInternal;
+ else if(strcmp(arg, "external") == 0)
+ linkmode = LinkExternal;
+ else if(strcmp(arg, "auto") == 0)
+ linkmode = LinkAuto;
+ else {
+ fprint(2, "unknown link mode -linkmode %s\n", arg);
+ errorexit();
}
}
diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c
index 2bbf4f83e..27041bc47 100644
--- a/src/cmd/ld/ldelf.c
+++ b/src/cmd/ld/ldelf.c
@@ -595,10 +595,8 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
s->sub = sect->sym->sub;
sect->sym->sub = s;
s->type = sect->sym->type | (s->type&~SMASK) | SSUB;
- if(!s->dynexport) {
+ if(!(s->cgoexport & CgoExportDynamic))
s->dynimplib = nil; // satisfy dynimport
- s->dynimpname = nil; // satisfy dynimport
- }
s->value = sym.value;
s->size = sym.size;
s->outer = sect->sym;
diff --git a/src/cmd/ld/ldmacho.c b/src/cmd/ld/ldmacho.c
index 41852f17c..098cb7bef 100644
--- a/src/cmd/ld/ldmacho.c
+++ b/src/cmd/ld/ldmacho.c
@@ -639,10 +639,8 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
s->size = (sym+1)->value - sym->value;
else
s->size = sect->addr + sect->size - sym->value;
- if(!s->dynexport) {
+ if(!(s->cgoexport & CgoExportDynamic))
s->dynimplib = nil; // satisfy dynimport
- s->dynimpname = nil; // satisfy dynimport
- }
if(outer->type == STEXT) {
Prog *p;
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
index 39c15e6a1..98923bfbf 100644
--- a/src/cmd/ld/ldpe.c
+++ b/src/cmd/ld/ldpe.c
@@ -135,7 +135,8 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
{
char *name;
int32 base;
- int i, j, l, numaux;
+ uint32 l;
+ int i, j, numaux;
PeObj *obj;
PeSect *sect, *rsect;
IMAGE_SECTION_HEADER sh;
@@ -170,11 +171,12 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
// TODO return error if found .cormeta
}
// load string table
- Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
- if(Bread(f, &l, sizeof l) != sizeof l)
+ Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*obj->fh.NumberOfSymbols, 0);
+ if(Bread(f, symbuf, 4) != 4)
goto bad;
+ l = le32(symbuf);
obj->snames = mal(l);
- Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
+ Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*obj->fh.NumberOfSymbols, 0);
if(Bread(f, obj->snames, l) != l)
goto bad;
// read symbols
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index 26fa4f2ac..18cae3175 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -44,6 +44,8 @@ int nlibdir = 0;
static int maxlibdir = 0;
static int cout = -1;
+static void hostlinksetup(void);
+
char* goroot;
char* goarch;
char* goos;
@@ -59,11 +61,7 @@ Lflag(char *arg)
maxlibdir = 8;
else
maxlibdir *= 2;
- p = realloc(libdir, maxlibdir * sizeof(*p));
- if (p == nil) {
- print("too many -L's: %d\n", nlibdir);
- usage();
- }
+ p = erealloc(libdir, maxlibdir * sizeof(*p));
libdir = p;
}
libdir[nlibdir++] = arg;
@@ -95,7 +93,7 @@ libinit(void)
#endif
cout = create(outfile, 1, 0775);
if(cout < 0) {
- diag("cannot create %s", outfile);
+ diag("cannot create %s: %r", outfile);
errorexit();
}
@@ -242,7 +240,7 @@ addlibpath(char *srcref, char *objref, char *file, char *pkg)
if(libraryp == nlibrary){
nlibrary = 50 + 2*libraryp;
- library = realloc(library, sizeof library[0] * nlibrary);
+ library = erealloc(library, sizeof library[0] * nlibrary);
}
l = &library[libraryp++];
@@ -288,7 +286,8 @@ loadinternal(char *name)
void
loadlib(void)
{
- int i;
+ int i, w, x;
+ Sym *s;
loadinternal("runtime");
if(thechar == '5')
@@ -303,6 +302,37 @@ loadlib(void)
objfile(library[i].file, library[i].pkg);
}
+ if(linkmode == LinkExternal && !iscgo)
+ linkmode = LinkInternal;
+
+ // If we got this far in automatic mode, there were no
+ // cgo uses that suggest we need external mode.
+ // Switch to internal.
+ if(linkmode == LinkAuto) {
+ linkmode = LinkInternal;
+ // Drop all the cgo_import_static declarations.
+ // Turns out we won't be needing them.
+ for(s = allsym; s != S; s = s->allsym)
+ if(s->type == SHOSTOBJ)
+ s->type = 0;
+ }
+
+ // Now that we know the link mode, trim the dynexp list.
+ x = CgoExportDynamic;
+ if(linkmode == LinkExternal)
+ x = CgoExportStatic;
+ w = 0;
+ for(i=0; i<ndynexp; i++)
+ if(dynexp[i]->cgoexport & x)
+ dynexp[w++] = dynexp[i];
+ ndynexp = w;
+
+ // In internal link mode, read the host object files.
+ if(linkmode == LinkInternal)
+ hostobjs();
+ else
+ hostlinksetup();
+
// 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)
@@ -316,7 +346,6 @@ loadlib(void)
debug['d'] = 1;
importcycles();
- sortdynexp();
}
/*
@@ -375,7 +404,7 @@ objfile(char *file, char *pkg)
/* load it as a regular file */
l = Bseek(f, 0L, 2);
Bseek(f, 0L, 0);
- ldobj(f, pkg, l, file, FileObj);
+ ldobj(f, pkg, l, file, file, FileObj);
Bterm(f);
free(pkg);
return;
@@ -434,7 +463,7 @@ objfile(char *file, char *pkg)
l--;
snprint(pname, sizeof pname, "%s(%.*s)", file, utfnlen(arhdr.name, l), arhdr.name);
l = atolwhex(arhdr.size);
- ldobj(f, pkg, l, pname, ArchiveObj);
+ ldobj(f, pkg, l, pname, file, ArchiveObj);
}
out:
@@ -442,8 +471,229 @@ out:
free(pkg);
}
+static void
+dowrite(int fd, char *p, int n)
+{
+ int m;
+
+ while(n > 0) {
+ m = write(fd, p, n);
+ if(m <= 0) {
+ cursym = S;
+ diag("write error: %r");
+ errorexit();
+ }
+ n -= m;
+ p += m;
+ }
+}
+
+typedef struct Hostobj Hostobj;
+
+struct Hostobj
+{
+ void (*ld)(Biobuf*, char*, int64, char*);
+ char *pkg;
+ char *pn;
+ char *file;
+ int64 off;
+ int64 len;
+};
+
+Hostobj *hostobj;
+int nhostobj;
+int mhostobj;
+
+// These packages can use internal linking mode.
+// Others trigger external mode.
+const char *internalpkg[] = {
+ "crypto/x509",
+ "net",
+ "os/user",
+ "runtime/cgo",
+ "runtime/race"
+};
+
+void
+ldhostobj(void (*ld)(Biobuf*, char*, int64, char*), Biobuf *f, char *pkg, int64 len, char *pn, char *file)
+{
+ int i, isinternal;
+ Hostobj *h;
+
+ isinternal = 0;
+ for(i=0; i<nelem(internalpkg); i++) {
+ if(strcmp(pkg, internalpkg[i]) == 0) {
+ isinternal = 1;
+ break;
+ }
+ }
+
+ if(!isinternal && linkmode == LinkAuto)
+ linkmode = LinkExternal;
+
+ if(nhostobj >= mhostobj) {
+ if(mhostobj == 0)
+ mhostobj = 16;
+ else
+ mhostobj *= 2;
+ hostobj = erealloc(hostobj, mhostobj*sizeof hostobj[0]);
+ }
+ h = &hostobj[nhostobj++];
+ h->ld = ld;
+ h->pkg = estrdup(pkg);
+ h->pn = estrdup(pn);
+ h->file = estrdup(file);
+ h->off = Boffset(f);
+ h->len = len;
+}
+
+void
+hostobjs(void)
+{
+ int i;
+ Biobuf *f;
+ Hostobj *h;
+
+ for(i=0; i<nhostobj; i++) {
+ h = &hostobj[i];
+ f = Bopen(h->file, OREAD);
+ if(f == nil) {
+ cursym = S;
+ diag("cannot reopen %s: %r", h->pn);
+ errorexit();
+ }
+ Bseek(f, h->off, 0);
+ h->ld(f, h->pkg, h->len, h->pn);
+ Bterm(f);
+ }
+}
+
+// provided by lib9
+int runcmd(char**);
+char* mktempdir(void);
+void removeall(char*);
+
+static void
+rmtemp(void)
+{
+ removeall(tmpdir);
+}
+
+static void
+hostlinksetup(void)
+{
+ char *p;
+
+ if(linkmode != LinkExternal)
+ return;
+
+ // create temporary directory and arrange cleanup
+ if(tmpdir == nil) {
+ tmpdir = mktempdir();
+ atexit(rmtemp);
+ }
+
+ // change our output to temporary object file
+ close(cout);
+ p = smprint("%s/go.o", tmpdir);
+ cout = create(p, 1, 0775);
+ if(cout < 0) {
+ diag("cannot create %s: %r", p);
+ errorexit();
+ }
+ free(p);
+}
+
void
-ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
+hostlink(void)
+{
+ char *p, **argv;
+ int i, w, n, argc, len;
+ Hostobj *h;
+ Biobuf *f;
+ static char buf[64<<10];
+
+ if(linkmode != LinkExternal || nerrors > 0)
+ return;
+
+ argv = malloc((10+nhostobj+nldflag)*sizeof argv[0]);
+ argc = 0;
+ // TODO: Add command-line flag to override gcc path and specify additional leading options.
+ // TODO: Add command-line flag to specify additional trailing options.
+ argv[argc++] = "gcc";
+ switch(thechar){
+ case '8':
+ argv[argc++] = "-m32";
+ break;
+ case '6':
+ argv[argc++] = "-m64";
+ break;
+ }
+ if(!debug['s'])
+ argv[argc++] = "-gdwarf-2";
+ if(HEADTYPE == Hdarwin)
+ argv[argc++] = "-Wl,-no_pie,-pagezero_size,4000000";
+ argv[argc++] = "-o";
+ argv[argc++] = outfile;
+
+ // Force global symbols to be exported for dlopen, etc.
+ // NOTE: May not work on OS X or Windows. We'll see.
+ argv[argc++] = "-rdynamic";
+
+ // already wrote main object file
+ // copy host objects to temporary directory
+ for(i=0; i<nhostobj; i++) {
+ h = &hostobj[i];
+ f = Bopen(h->file, OREAD);
+ if(f == nil) {
+ cursym = S;
+ diag("cannot reopen %s: %r", h->pn);
+ errorexit();
+ }
+ Bseek(f, h->off, 0);
+ p = smprint("%s/%06d.o", tmpdir, i);
+ argv[argc++] = p;
+ w = create(p, 1, 0775);
+ if(w < 0) {
+ diag("cannot create %s: %r", p);
+ errorexit();
+ }
+ len = h->len;
+ while(len > 0 && (n = Bread(f, buf, sizeof buf)) > 0){
+ if(n > len)
+ n = len;
+ dowrite(w, buf, n);
+ len -= n;
+ }
+ if(close(w) < 0) {
+ diag("cannot write %s: %r", p);
+ errorexit();
+ }
+ Bterm(f);
+ }
+
+ argv[argc++] = smprint("%s/go.o", tmpdir);
+ for(i=0; i<nldflag; i++)
+ argv[argc++] = ldflag[i];
+ argv[argc] = nil;
+
+ quotefmtinstall();
+ if(debug['v']) {
+ Bprint(&bso, "host link:");
+ for(i=0; i<argc; i++)
+ Bprint(&bso, " %q", argv[i]);
+ Bprint(&bso, "\n");
+ Bflush(&bso);
+ }
+
+ if(runcmd(argv) < 0) {
+ diag("%s: running %s failed: %r", argv0, argv[0]);
+ errorexit();
+ }
+}
+
+void
+ldobj(Biobuf *f, char *pkg, int64 len, char *pn, char *file, int whence)
{
char *line;
int n, c1, c2, c3, c4;
@@ -453,7 +703,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
eof = Boffset(f) + len;
- pn = strdup(pn);
+ pn = estrdup(pn);
c1 = Bgetc(f);
c2 = Bgetc(f);
@@ -466,18 +716,15 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
magic = c1<<24 | c2<<16 | c3<<8 | c4;
if(magic == 0x7f454c46) { // \x7F E L F
- ldelf(f, pkg, len, pn);
- free(pn);
+ ldhostobj(ldelf, f, pkg, len, pn, file);
return;
}
if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) {
- ldmacho(f, pkg, len, pn);
- free(pn);
+ ldhostobj(ldmacho, f, pkg, len, pn, file);
return;
}
if(c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86) {
- ldpe(f, pkg, len, pn);
- free(pn);
+ ldhostobj(ldpe, f, pkg, len, pn, file);
return;
}
@@ -524,7 +771,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
line[n] = '\0';
if(n-10 > strlen(t)) {
if(theline == nil)
- theline = strdup(line+10);
+ theline = estrdup(line+10);
else if(strcmp(theline, line+10) != 0) {
line[n] = '\0';
diag("%s: object is [%s] expected [%s]", pn, line+10, theline);
@@ -615,6 +862,7 @@ _lookup(char *symb, int v, int creat)
return nil;
s = newsym(symb, v);
+ s->extname = s->name;
s->hash = hash[h];
hash[h] = s;
@@ -1027,6 +1275,7 @@ addsection(Segment *seg, char *name, int rwx)
sect->rwx = rwx;
sect->name = name;
sect->seg = seg;
+ sect->align = PtrSize; // everything is at least pointer-aligned
*l = sect;
return sect;
}
@@ -1460,23 +1709,6 @@ Yconv(Fmt *fp)
vlong coutpos;
-static void
-dowrite(int fd, char *p, int n)
-{
- int m;
-
- while(n > 0) {
- m = write(fd, p, n);
- if(m <= 0) {
- cursym = S;
- diag("write error: %r");
- errorexit();
- }
- n -= m;
- p += m;
- }
-}
-
void
cflush(void)
{
@@ -1576,7 +1808,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
put(s, s->name, 'T', s->value, s->size, s->version, 0);
for(s=allsym; s!=S; s=s->allsym) {
- if(s->hide)
+ if(s->hide || (s->name[0] == '.' && s->version == 0 && strcmp(s->name, ".rathole") != 0))
continue;
switch(s->type&SMASK) {
case SCONST:
@@ -1591,8 +1823,6 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
case SSTRING:
case SGOSTRING:
case SWINDOWS:
- case SGCDATA:
- case SGCBSS:
if(!s->reachable)
continue;
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
@@ -1664,3 +1894,27 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
Bprint(&bso, "symsize = %ud\n", symsize);
Bflush(&bso);
}
+
+char*
+estrdup(char *p)
+{
+ p = strdup(p);
+ if(p == nil) {
+ cursym = S;
+ diag("out of memory");
+ errorexit();
+ }
+ return p;
+}
+
+void*
+erealloc(void *p, long n)
+{
+ p = realloc(p, n);
+ if(p == nil) {
+ cursym = S;
+ diag("out of memory");
+ errorexit();
+ }
+ return p;
+}
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 94ad76ecc..a5ca7d3c3 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -34,30 +34,28 @@ enum
/* order here is order in output file */
STEXT,
- SMACHOPLT,
STYPE,
SSTRING,
SGOSTRING,
SRODATA,
STYPELINK,
- SGCDATA,
- SGCBSS,
SSYMTAB,
SPCLNTAB,
SELFROSECT,
+ SMACHOPLT,
SELFSECT,
+ SMACHO, /* Mach-O __nl_symbol_ptr */
+ SMACHOGOT,
SNOPTRDATA,
SDATARELRO,
SDATA,
- SMACHO, /* Mach-O __nl_symbol_ptr */
- SMACHOGOT,
SWINDOWS,
SBSS,
SNOPTRBSS,
SXREF,
- SMACHODYNSTR,
- SMACHODYNSYM,
+ SMACHOSYMSTR,
+ SMACHOSYMTAB,
SMACHOINDIRECTPLT,
SMACHOINDIRECTGOT,
SFILE,
@@ -104,6 +102,8 @@ struct Segment
struct Section
{
uchar rwx;
+ int16 extnum;
+ int32 align;
char *name;
uvlong vaddr;
uvlong len;
@@ -138,20 +138,38 @@ EXTERN char* outfile;
EXTERN int32 nsymbol;
EXTERN char* thestring;
EXTERN int ndynexp;
+EXTERN Sym** dynexp;
+EXTERN int nldflag;
+EXTERN char** ldflag;
EXTERN int havedynamic;
EXTERN int iscgo;
-EXTERN int isobj;
EXTERN int elfglobalsymndx;
EXTERN int flag_race;
EXTERN int flag_shared;
EXTERN char* tracksym;
EXTERN char* interpreter;
+EXTERN char* tmpdir;
+
+enum
+{
+ LinkAuto = 0,
+ LinkInternal,
+ LinkExternal,
+};
+EXTERN int linkmode;
+
+// for dynexport field of Sym
+enum
+{
+ CgoExportDynamic = 1<<0,
+ CgoExportStatic = 1<<1,
+};
EXTERN Segment segtext;
EXTERN Segment segdata;
-EXTERN Segment segsym;
-EXTERN Segment segdwarf;
+EXTERN Segment segdwarf;
+void setlinkmode(char*);
void addlib(char *src, char *obj);
void addlibpath(char *srcref, char *objref, char *file, char *pkg);
Section* addsection(Segment*, char*, int);
@@ -185,7 +203,7 @@ void adddynrel(Sym*, Reloc*);
void adddynrela(Sym*, Sym*, Reloc*);
Sym* lookuprel(void);
void ldobj1(Biobuf *f, char*, int64 len, char *pn);
-void ldobj(Biobuf*, char*, int64, char*, int);
+void ldobj(Biobuf*, char*, int64, char*, char*, int);
void ldelf(Biobuf*, char*, int64, char*);
void ldmacho(Biobuf*, char*, int64, char*);
void ldpe(Biobuf*, char*, int64, char*);
@@ -207,6 +225,7 @@ vlong adduint8(Sym*, uint8);
vlong adduint16(Sym*, uint16);
vlong adduint32(Sym*, uint32);
vlong adduint64(Sym*, uint64);
+vlong adduintxx(Sym*, uint64, int);
vlong addaddr(Sym*, Sym*);
vlong addaddrplus(Sym*, Sym*, int32);
vlong addpcrelplus(Sym*, Sym*, int32);
@@ -240,6 +259,10 @@ void usage(void);
void setinterp(char*);
Sym* listsort(Sym*, int(*cmp)(Sym*, Sym*), int);
int valuecmp(Sym*, Sym*);
+void hostobjs(void);
+void hostlink(void);
+char* estrdup(char*);
+void* erealloc(void*, long);
int pathchar(void);
void* mal(uint32);
@@ -359,5 +382,3 @@ char* decodetype_structfieldname(Sym*, int);
Sym* decodetype_structfieldtype(Sym*, int);
vlong decodetype_structfieldoffs(Sym*, int);
vlong decodetype_ifacemethodcount(Sym*);
-
-void sortdynexp(void);
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index 6781c25a4..d135a92da 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -14,9 +14,20 @@ static int macho64;
static MachoHdr hdr;
static MachoLoad *load;
static MachoSeg seg[16];
-static MachoDebug xdebug[16];
static int nload, mload, nseg, ndebug, nsect;
+enum
+{
+ SymKindLocal = 0,
+ SymKindExtdef,
+ SymKindUndef,
+ NumSymKind
+};
+
+static int nkind[NumSymKind];
+static Sym** sortsym;
+static int nsortsym;
+
// 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
@@ -25,6 +36,8 @@ static int nload, mload, nseg, ndebug, nsect;
// up about 1300 bytes; we overestimate that as 2k.
static int load_budget = INITIAL_MACHO_HEADR - 2*1024;
+static void machodysymtab(void);
+
void
machoinit(void)
{
@@ -56,11 +69,7 @@ newMachoLoad(uint32 type, uint32 ndata)
mload = 1;
else
mload *= 2;
- load = realloc(load, mload*sizeof load[0]);
- if(load == nil) {
- diag("out of memory");
- errorexit();
- }
+ load = erealloc(load, mload*sizeof load[0]);
}
if(macho64 && (ndata & 1))
@@ -90,7 +99,7 @@ newMachoSeg(char *name, int msect)
}
MachoSect*
-newMachoSect(MachoSeg *seg, char *name)
+newMachoSect(MachoSeg *seg, char *name, char *segname)
{
MachoSect *s;
@@ -100,21 +109,11 @@ newMachoSect(MachoSeg *seg, char *name)
}
s = &seg->sect[seg->nsect++];
s->name = name;
+ s->segname = segname;
nsect++;
return s;
}
-MachoDebug*
-newMachoDebug(void)
-{
- if(ndebug >= nelem(xdebug)) {
- diag("too many debugs");
- errorexit();
- }
- return &xdebug[ndebug++];
-}
-
-
// Generic linking code.
static char **dylib;
@@ -130,7 +129,6 @@ machowrite(void)
int i, j;
MachoSeg *s;
MachoSect *t;
- MachoDebug *d;
MachoLoad *l;
o1 = cpos();
@@ -152,7 +150,10 @@ machowrite(void)
LPUT(0xfeedface);
LPUT(hdr.cpu);
LPUT(hdr.subcpu);
- LPUT(2); /* file type - mach executable */
+ if(linkmode == LinkExternal)
+ LPUT(1); /* file type - mach object */
+ else
+ LPUT(2); /* file type - mach executable */
LPUT(nload+nseg+ndebug);
LPUT(loadsize);
LPUT(1); /* flags - no undefines */
@@ -190,7 +191,7 @@ machowrite(void)
t = &s->sect[j];
if(macho64) {
strnput(t->name, 16);
- strnput(s->name, 16);
+ strnput(t->segname, 16);
VPUT(t->addr);
VPUT(t->size);
LPUT(t->off);
@@ -203,7 +204,7 @@ machowrite(void)
LPUT(0); /* reserved */
} else {
strnput(t->name, 16);
- strnput(s->name, 16);
+ strnput(t->segname, 16);
LPUT(t->addr);
LPUT(t->size);
LPUT(t->off);
@@ -225,14 +226,6 @@ machowrite(void)
LPUT(l->data[j]);
}
- for(i=0; i<ndebug; i++) {
- d = &xdebug[i];
- LPUT(3); /* obsolete gdb debug info */
- LPUT(16); /* size of symseg command */
- LPUT(d->fileoffset);
- LPUT(d->filesize);
- }
-
return cpos() - o1;
}
@@ -245,31 +238,34 @@ domacho(void)
return;
// empirically, string table must begin with " \x00".
- s = lookup(".dynstr", 0);
- s->type = SMACHODYNSTR;
+ s = lookup(".machosymstr", 0);
+ s->type = SMACHOSYMSTR;
s->reachable = 1;
adduint8(s, ' ');
adduint8(s, '\0');
- s = lookup(".dynsym", 0);
- s->type = SMACHODYNSYM;
+ s = lookup(".machosymtab", 0);
+ s->type = SMACHOSYMTAB;
s->reachable = 1;
- s = lookup(".plt", 0); // will be __symbol_stub
- s->type = SMACHOPLT;
- s->reachable = 1;
+ if(linkmode != LinkExternal) {
+ s = lookup(".plt", 0); // will be __symbol_stub
+ s->type = SMACHOPLT;
+ s->reachable = 1;
- s = lookup(".got", 0); // will be __nl_symbol_ptr
- s->type = SMACHOGOT;
- s->reachable = 1;
+ s = lookup(".got", 0); // will be __nl_symbol_ptr
+ s->type = SMACHOGOT;
+ s->reachable = 1;
+ s->align = 4;
- s = lookup(".linkedit.plt", 0); // indirect table for .plt
- s->type = SMACHOINDIRECTPLT;
- s->reachable = 1;
+ s = lookup(".linkedit.plt", 0); // indirect table for .plt
+ s->type = SMACHOINDIRECTPLT;
+ s->reachable = 1;
- s = lookup(".linkedit.got", 0); // indirect table for .got
- s->type = SMACHOINDIRECTGOT;
- s->reachable = 1;
+ s = lookup(".linkedit.got", 0); // indirect table for .got
+ s->type = SMACHOINDIRECTGOT;
+ s->reachable = 1;
+ }
}
void
@@ -286,16 +282,62 @@ machoadddynlib(char *lib)
load_budget += 4096;
}
- if(ndylib%32 == 0) {
- dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
- if(dylib == nil) {
- diag("out of memory");
- errorexit();
- }
- }
+ if(ndylib%32 == 0)
+ dylib = erealloc(dylib, (ndylib+32)*sizeof dylib[0]);
dylib[ndylib++] = lib;
}
+static void
+machoshbits(MachoSeg *mseg, Section *sect, char *segname)
+{
+ MachoSect *msect;
+ char buf[40];
+ char *p;
+
+ snprint(buf, sizeof buf, "__%s", sect->name+1);
+ for(p=buf; *p; p++)
+ if(*p == '.')
+ *p = '_';
+
+ msect = newMachoSect(mseg, estrdup(buf), segname);
+ if(sect->rellen > 0) {
+ msect->reloc = sect->reloff;
+ msect->nreloc = sect->rellen / 8;
+ }
+
+ while(1<<msect->align < sect->align)
+ msect->align++;
+ msect->addr = sect->vaddr;
+ msect->size = sect->len;
+
+ if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen) {
+ // data in file
+ if(sect->len > sect->seg->vaddr + sect->seg->filelen - sect->vaddr)
+ diag("macho cannot represent section %s crossing data and bss", sect->name);
+ msect->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
+ } else {
+ // zero fill
+ msect->off = 0;
+ msect->flag |= 1;
+ }
+
+ if(sect->rwx & 1)
+ msect->flag |= 0x400; /* has instructions */
+
+ if(strcmp(sect->name, ".plt") == 0) {
+ msect->name = "__symbol_stub1";
+ msect->flag = 0x80000408; /* only instructions, code, symbol stubs */
+ msect->res1 = 0;//nkind[SymKindLocal];
+ msect->res2 = 6;
+ }
+
+ if(strcmp(sect->name, ".got") == 0) {
+ msect->name = "__nl_symbol_ptr";
+ msect->flag = 6; /* section with nonlazy symbol pointers */
+ msect->res1 = lookup(".linkedit.plt", 0)->size / 4; /* offset into indirect symbol table */
+ }
+}
+
void
asmbmacho(void)
{
@@ -303,11 +345,9 @@ asmbmacho(void)
vlong va;
int a, i;
MachoHdr *mh;
- MachoSect *msect;
MachoSeg *ms;
- MachoDebug *md;
MachoLoad *ml;
- Sym *s;
+ Section *sect;
/* apple MACH */
va = INITTEXT - HEADR;
@@ -325,179 +365,305 @@ asmbmacho(void)
mh->subcpu = MACHO_SUBCPU_X86;
break;
}
+
+ ms = nil;
+ if(linkmode == LinkExternal) {
+ /* segment for entire file */
+ ms = newMachoSeg("", 40);
+ ms->fileoffset = segtext.fileoff;
+ ms->filesize = segdata.fileoff + segdata.filelen - segtext.fileoff;
+ }
/* segment for zero page */
- ms = newMachoSeg("__PAGEZERO", 0);
- ms->vsize = va;
+ if(linkmode != LinkExternal) {
+ ms = newMachoSeg("__PAGEZERO", 0);
+ ms->vsize = va;
+ }
/* text */
v = rnd(HEADR+segtext.len, INITRND);
- ms = newMachoSeg("__TEXT", 2);
- ms->vaddr = va;
- ms->vsize = v;
- ms->filesize = v;
- ms->prot1 = 7;
- ms->prot2 = 5;
-
- msect = newMachoSect(ms, "__text");
- msect->addr = INITTEXT;
- msect->size = segtext.sect->len;
- msect->off = INITTEXT - va;
- msect->flag = 0x400; /* flag - some instructions */
-
- s = lookup(".plt", 0);
- if(s->size > 0) {
- msect = newMachoSect(ms, "__symbol_stub1");
- msect->addr = symaddr(s);
- msect->size = s->size;
- msect->off = ms->fileoffset + msect->addr - ms->vaddr;
- msect->flag = 0x80000408; /* flag */
- msect->res1 = 0; /* index into indirect symbol table */
- msect->res2 = 6; /* size of stubs */
+ if(linkmode != LinkExternal) {
+ ms = newMachoSeg("__TEXT", 20);
+ ms->vaddr = va;
+ ms->vsize = v;
+ ms->fileoffset = 0;
+ ms->filesize = v;
+ ms->prot1 = 7;
+ ms->prot2 = 5;
}
+ for(sect=segtext.sect; sect!=nil; sect=sect->next)
+ machoshbits(ms, sect, "__TEXT");
+
/* data */
- w = segdata.len;
- ms = newMachoSeg("__DATA", 3);
- ms->vaddr = va+v;
- ms->vsize = w;
- ms->fileoffset = v;
- ms->filesize = segdata.filelen;
- ms->prot1 = 7;
- ms->prot2 = 3;
-
- msect = newMachoSect(ms, "__data");
- msect->addr = va+v;
- msect->off = v;
- msect->size = segdata.filelen;
-
- s = lookup(".got", 0);
- if(s->size > 0) {
- msect->size = symaddr(s) - msect->addr;
-
- msect = newMachoSect(ms, "__nl_symbol_ptr");
- msect->addr = symaddr(s);
- msect->size = s->size;
- msect->off = datoff(msect->addr);
- msect->align = 2;
- msect->flag = 6; /* section with nonlazy symbol pointers */
- msect->res1 = lookup(".linkedit.plt", 0)->size / 4; /* offset into indirect symbol table */
+ if(linkmode != LinkExternal) {
+ w = segdata.len;
+ ms = newMachoSeg("__DATA", 20);
+ ms->vaddr = va+v;
+ ms->vsize = w;
+ ms->fileoffset = v;
+ ms->filesize = segdata.filelen;
+ ms->prot1 = 3;
+ ms->prot2 = 3;
}
- msect = newMachoSect(ms, "__bss");
- msect->addr = va+v+segdata.filelen;
- msect->size = segdata.len - segdata.filelen;
- msect->flag = 1; /* flag - zero fill */
+ for(sect=segdata.sect; sect!=nil; sect=sect->next)
+ machoshbits(ms, sect, "__DATA");
- switch(thechar) {
- default:
- diag("unknown macho architecture");
- errorexit();
- case '6':
- ml = newMachoLoad(5, 42+2); /* unix thread */
- ml->data[0] = 4; /* thread type */
- ml->data[1] = 42; /* word count */
- ml->data[2+32] = entryvalue(); /* start pc */
- ml->data[2+32+1] = entryvalue()>>16>>16; // hide >>32 for 8l
- break;
- case '8':
- ml = newMachoLoad(5, 16+2); /* unix thread */
- ml->data[0] = 1; /* thread type */
- ml->data[1] = 16; /* word count */
- ml->data[2+10] = entryvalue(); /* start pc */
- break;
+ if(linkmode != LinkExternal) {
+ switch(thechar) {
+ default:
+ diag("unknown macho architecture");
+ errorexit();
+ case '6':
+ ml = newMachoLoad(5, 42+2); /* unix thread */
+ ml->data[0] = 4; /* thread type */
+ ml->data[1] = 42; /* word count */
+ ml->data[2+32] = entryvalue(); /* start pc */
+ ml->data[2+32+1] = entryvalue()>>16>>16; // hide >>32 for 8l
+ break;
+ case '8':
+ ml = newMachoLoad(5, 16+2); /* unix thread */
+ ml->data[0] = 1; /* thread type */
+ ml->data[1] = 16; /* word count */
+ ml->data[2+10] = entryvalue(); /* start pc */
+ break;
+ }
}
-
+
if(!debug['d']) {
Sym *s1, *s2, *s3, *s4;
// must match domacholink below
- s1 = lookup(".dynsym", 0);
+ s1 = lookup(".machosymtab", 0);
s2 = lookup(".linkedit.plt", 0);
s3 = lookup(".linkedit.got", 0);
- s4 = lookup(".dynstr", 0);
-
- ms = newMachoSeg("__LINKEDIT", 0);
- ms->vaddr = va+v+rnd(segdata.len, INITRND);
- ms->vsize = s1->size + s2->size + s3->size + s4->size;
- ms->fileoffset = linkoff;
- ms->filesize = ms->vsize;
- ms->prot1 = 7;
- ms->prot2 = 3;
+ s4 = lookup(".machosymstr", 0);
+
+ if(linkmode != LinkExternal) {
+ ms = newMachoSeg("__LINKEDIT", 0);
+ ms->vaddr = va+v+rnd(segdata.len, INITRND);
+ ms->vsize = s1->size + s2->size + s3->size + s4->size;
+ ms->fileoffset = linkoff;
+ ms->filesize = ms->vsize;
+ ms->prot1 = 7;
+ ms->prot2 = 3;
+ }
ml = newMachoLoad(2, 4); /* LC_SYMTAB */
ml->data[0] = linkoff; /* symoff */
- ml->data[1] = s1->size / (macho64 ? 16 : 12); /* nsyms */
+ ml->data[1] = nsortsym; /* nsyms */
ml->data[2] = linkoff + s1->size + s2->size + s3->size; /* stroff */
ml->data[3] = s4->size; /* strsize */
- ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
- ml->data[0] = 0; /* ilocalsym */
- ml->data[1] = 0; /* nlocalsym */
- ml->data[2] = 0; /* iextdefsym */
- ml->data[3] = ndynexp; /* nextdefsym */
- ml->data[4] = ndynexp; /* iundefsym */
- ml->data[5] = (s1->size / (macho64 ? 16 : 12)) - ndynexp; /* nundefsym */
- ml->data[6] = 0; /* tocoffset */
- ml->data[7] = 0; /* ntoc */
- ml->data[8] = 0; /* modtaboff */
- ml->data[9] = 0; /* nmodtab */
- ml->data[10] = 0; /* extrefsymoff */
- ml->data[11] = 0; /* nextrefsyms */
- ml->data[12] = linkoff + s1->size; /* indirectsymoff */
- ml->data[13] = (s2->size + s3->size) / 4; /* nindirectsyms */
- ml->data[14] = 0; /* extreloff */
- ml->data[15] = 0; /* nextrel */
- ml->data[16] = 0; /* locreloff */
- ml->data[17] = 0; /* nlocrel */
-
- ml = newMachoLoad(14, 6); /* LC_LOAD_DYLINKER */
- ml->data[0] = 12; /* offset to string */
- strcpy((char*)&ml->data[1], "/usr/lib/dyld");
-
- for(i=0; i<ndylib; i++) {
- ml = newMachoLoad(12, 4+(strlen(dylib[i])+1+7)/8*2); /* LC_LOAD_DYLIB */
- ml->data[0] = 24; /* offset of string from beginning of load */
- ml->data[1] = 0; /* time stamp */
- ml->data[2] = 0; /* version */
- ml->data[3] = 0; /* compatibility version */
- strcpy((char*)&ml->data[4], dylib[i]);
+ machodysymtab();
+
+ if(linkmode != LinkExternal) {
+ ml = newMachoLoad(14, 6); /* LC_LOAD_DYLINKER */
+ ml->data[0] = 12; /* offset to string */
+ strcpy((char*)&ml->data[1], "/usr/lib/dyld");
+
+ for(i=0; i<ndylib; i++) {
+ ml = newMachoLoad(12, 4+(strlen(dylib[i])+1+7)/8*2); /* LC_LOAD_DYLIB */
+ ml->data[0] = 24; /* offset of string from beginning of load */
+ ml->data[1] = 0; /* time stamp */
+ ml->data[2] = 0; /* version */
+ ml->data[3] = 0; /* compatibility version */
+ strcpy((char*)&ml->data[4], dylib[i]);
+ }
}
}
- if(!debug['s']) {
- Sym *s;
-
- md = newMachoDebug();
- s = lookup("symtab", 0);
- md->fileoffset = datoff(s->value);
- md->filesize = s->size;
-
- md = newMachoDebug();
- s = lookup("pclntab", 0);
- md->fileoffset = datoff(s->value);
- md->filesize = s->size;
-
+ // TODO: dwarf headers go in ms too
+ if(!debug['s'] && linkmode != LinkExternal)
dwarfaddmachoheaders();
- }
a = machowrite();
if(a > HEADR)
diag("HEADR too small: %d > %d", a, HEADR);
}
+static int
+symkind(Sym *s)
+{
+ if(s->type == SDYNIMPORT)
+ return SymKindUndef;
+ if(s->cgoexport)
+ return SymKindExtdef;
+ return SymKindLocal;
+}
+
+static void
+addsym(Sym *s, char *name, int type, vlong addr, vlong size, int ver, Sym *gotype)
+{
+ USED(name);
+ USED(addr);
+ USED(size);
+ USED(ver);
+ USED(gotype);
+
+ if(s == nil)
+ return;
+
+ switch(type) {
+ default:
+ return;
+ case 'D':
+ case 'B':
+ case 'T':
+ break;
+ }
+
+ if(sortsym) {
+ sortsym[nsortsym] = s;
+ nkind[symkind(s)]++;
+ }
+ nsortsym++;
+}
+
+static int
+scmp(const void *p1, const void *p2)
+{
+ Sym *s1, *s2;
+ int k1, k2;
+
+ s1 = *(Sym**)p1;
+ s2 = *(Sym**)p2;
+
+ k1 = symkind(s1);
+ k2 = symkind(s2);
+ if(k1 != k2)
+ return k1 - k2;
+
+ return strcmp(s1->extname, s2->extname);
+}
+
+static void
+machogenasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
+{
+ Sym *s;
+
+ genasmsym(put);
+ for(s=allsym; s; s=s->allsym)
+ if(s->type == SDYNIMPORT || s->type == SHOSTOBJ)
+ if(s->reachable)
+ put(s, nil, 'D', 0, 0, 0, nil);
+}
+
+void
+machosymorder(void)
+{
+ int i;
+
+ // On Mac OS X Mountain Lion, we must sort exported symbols
+ // So we sort them here and pre-allocate dynid for them
+ // See http://golang.org/issue/4029
+ for(i=0; i<ndynexp; i++)
+ dynexp[i]->reachable = 1;
+ machogenasmsym(addsym);
+ sortsym = mal(nsortsym * sizeof sortsym[0]);
+ nsortsym = 0;
+ machogenasmsym(addsym);
+ qsort(sortsym, nsortsym, sizeof sortsym[0], scmp);
+ for(i=0; i<nsortsym; i++)
+ sortsym[i]->dynid = i;
+}
+
+static void
+machosymtab(void)
+{
+ int i;
+ Sym *symtab, *symstr, *s, *o;
+
+ symtab = lookup(".machosymtab", 0);
+ symstr = lookup(".machosymstr", 0);
+
+ for(i=0; i<nsortsym; i++) {
+ s = sortsym[i];
+ adduint32(symtab, symstr->size);
+
+ // Only add _ to C symbols. Go symbols have dot in the name.
+ if(strstr(s->extname, ".") == nil)
+ adduint8(symstr, '_');
+ addstring(symstr, s->extname);
+ if(s->type == SDYNIMPORT || s->type == SHOSTOBJ) {
+ adduint8(symtab, 0x01); // type N_EXT, external symbol
+ adduint8(symtab, 0); // no section
+ adduint16(symtab, 0); // desc
+ adduintxx(symtab, 0, PtrSize); // no value
+ } else {
+ if(s->cgoexport)
+ adduint8(symtab, 0x0f);
+ else
+ adduint8(symtab, 0x0e);
+ o = s;
+ while(o->outer != nil)
+ o = o->outer;
+ if(o->sect == nil) {
+ diag("missing section for %s", s->name);
+ adduint8(symtab, 0);
+ } else
+ adduint8(symtab, o->sect->extnum);
+ adduint16(symtab, 0); // desc
+ adduintxx(symtab, symaddr(s), PtrSize);
+ }
+ }
+}
+
+static void
+machodysymtab(void)
+{
+ int n;
+ MachoLoad *ml;
+ Sym *s1, *s2, *s3;
+
+ ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
+
+ n = 0;
+ ml->data[0] = n; /* ilocalsym */
+ ml->data[1] = nkind[SymKindLocal]; /* nlocalsym */
+ n += nkind[SymKindLocal];
+
+ ml->data[2] = n; /* iextdefsym */
+ ml->data[3] = nkind[SymKindExtdef]; /* nextdefsym */
+ n += nkind[SymKindExtdef];
+
+ ml->data[4] = n; /* iundefsym */
+ ml->data[5] = nkind[SymKindUndef]; /* nundefsym */
+
+ ml->data[6] = 0; /* tocoffset */
+ ml->data[7] = 0; /* ntoc */
+ ml->data[8] = 0; /* modtaboff */
+ ml->data[9] = 0; /* nmodtab */
+ ml->data[10] = 0; /* extrefsymoff */
+ ml->data[11] = 0; /* nextrefsyms */
+
+ // must match domacholink below
+ s1 = lookup(".machosymtab", 0);
+ s2 = lookup(".linkedit.plt", 0);
+ s3 = lookup(".linkedit.got", 0);
+ ml->data[12] = linkoff + s1->size; /* indirectsymoff */
+ ml->data[13] = (s2->size + s3->size) / 4; /* nindirectsyms */
+
+ ml->data[14] = 0; /* extreloff */
+ ml->data[15] = 0; /* nextrel */
+ ml->data[16] = 0; /* locreloff */
+ ml->data[17] = 0; /* nlocrel */
+}
+
vlong
domacholink(void)
{
int size;
Sym *s1, *s2, *s3, *s4;
+ machosymtab();
+
// write data that will be linkedit section
- s1 = lookup(".dynsym", 0);
- relocsym(s1);
+ s1 = lookup(".machosymtab", 0);
s2 = lookup(".linkedit.plt", 0);
s3 = lookup(".linkedit.got", 0);
- s4 = lookup(".dynstr", 0);
+ s4 = lookup(".machosymstr", 0);
// Force the linkedit section to end on a 16-byte
// boundary. This allows pure (non-cgo) Go binaries
@@ -533,3 +699,57 @@ domacholink(void)
return rnd(size, INITRND);
}
+
+
+void
+machorelocsect(Section *sect, Sym *first)
+{
+ Sym *sym;
+ int32 eaddr;
+ Reloc *r;
+
+ // If main section has no bits, nothing to relocate.
+ if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen)
+ return;
+
+ sect->reloff = cpos();
+ for(sym = first; sym != nil; sym = sym->next) {
+ if(!sym->reachable)
+ continue;
+ if(sym->value >= sect->vaddr)
+ break;
+ }
+
+ eaddr = sect->vaddr + sect->len;
+ for(; sym != nil; sym = sym->next) {
+ if(!sym->reachable)
+ continue;
+ if(sym->value >= eaddr)
+ break;
+ cursym = sym;
+
+ for(r = sym->r; r < sym->r+sym->nr; r++) {
+ if(r->done)
+ continue;
+ if(machoreloc1(r, sym->value+r->off - sect->vaddr) < 0)
+ diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
+ }
+ }
+
+ sect->rellen = cpos() - sect->reloff;
+}
+
+void
+machoemitreloc(void)
+{
+ Section *sect;
+
+ while(cpos()&7)
+ cput(0);
+
+ machorelocsect(segtext.sect, textp);
+ for(sect=segtext.sect->next; sect!=nil; sect=sect->next)
+ machorelocsect(sect, datap);
+ for(sect=segdata.sect; sect!=nil; sect=sect->next)
+ machorelocsect(sect, datap);
+}
diff --git a/src/cmd/ld/macho.h b/src/cmd/ld/macho.h
index baea6ff03..d759f4b0f 100644
--- a/src/cmd/ld/macho.h
+++ b/src/cmd/ld/macho.h
@@ -11,6 +11,7 @@ struct MachoHdr {
typedef struct MachoSect MachoSect;
struct MachoSect {
char* name;
+ char* segname;
uint64 addr;
uint64 size;
uint32 off;
@@ -44,19 +45,15 @@ struct MachoLoad {
uint32 *data;
};
-typedef struct MachoDebug MachoDebug;
-struct MachoDebug {
- uint32 fileoffset;
- uint32 filesize;
-};
-
MachoHdr* getMachoHdr(void);
MachoSeg* newMachoSeg(char*, int);
-MachoSect* newMachoSect(MachoSeg*, char*);
+MachoSect* newMachoSect(MachoSeg*, char*, char*);
MachoLoad* newMachoLoad(uint32, uint32);
-MachoDebug* newMachoDebug(void);
int machowrite(void);
void machoinit(void);
+void machosymorder(void);
+void machoemitreloc(void);
+int machoreloc1(Reloc*, vlong);
/*
* Total amount of space to reserve at the start of the file
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
index f2903ba0f..090d083f5 100644
--- a/src/cmd/ld/pe.c
+++ b/src/cmd/ld/pe.c
@@ -195,7 +195,7 @@ initdynimport(void)
dr = nil;
m = nil;
for(s = allsym; s != S; s = s->allsym) {
- if(!s->reachable || !s->dynimpname || s->dynexport)
+ if(!s->reachable || s->type != SDYNIMPORT)
continue;
for(d = dr; d != nil; d = d->next) {
if(strcmp(d->name,s->dynimplib) == 0) {
@@ -262,7 +262,7 @@ addimports(IMAGE_SECTION_HEADER *datsect)
for(m = d->ms; m != nil; m = m->next) {
m->off = nextsectoff + cpos() - startoff;
wputl(0); // hint
- strput(m->s->dynimpname);
+ strput(m->s->extname);
}
}
@@ -325,7 +325,7 @@ scmp(const void *p1, const void *p2)
s1 = *(Sym**)p1;
s2 = *(Sym**)p2;
- return strcmp(s1->dynimpname, s2->dynimpname);
+ return strcmp(s1->extname, s2->extname);
}
static void
@@ -335,7 +335,7 @@ initdynexport(void)
nexport = 0;
for(s = allsym; s != S; s = s->allsym) {
- if(!s->reachable || !s->dynimpname || !s->dynexport)
+ if(!s->reachable || !(s->cgoexport & CgoExportDynamic))
continue;
if(nexport+1 > sizeof(dexport)/sizeof(dexport[0])) {
diag("pe dynexport table is full");
@@ -358,7 +358,7 @@ addexports(void)
size = sizeof e + 10*nexport + strlen(outfile) + 1;
for(i=0; i<nexport; i++)
- size += strlen(dexport[i]->dynimpname) + 1;
+ size += strlen(dexport[i]->extname) + 1;
if (nexport == 0)
return;
@@ -394,7 +394,7 @@ addexports(void)
v = e.Name + strlen(outfile)+1;
for(i=0; i<nexport; i++) {
lputl(v);
- v += strlen(dexport[i]->dynimpname)+1;
+ v += strlen(dexport[i]->extname)+1;
}
// put EXPORT Ordinal Table
for(i=0; i<nexport; i++)
@@ -402,7 +402,7 @@ addexports(void)
// put Names
strnput(outfile, strlen(outfile)+1);
for(i=0; i<nexport; i++)
- strnput(dexport[i]->dynimpname, strlen(dexport[i]->dynimpname)+1);
+ strnput(dexport[i]->extname, strlen(dexport[i]->extname)+1);
strnput("", sect->SizeOfRawData - size);
}
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index 89a594872..698194f84 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -121,12 +121,22 @@ putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
// One pass for each binding: STB_LOCAL, STB_GLOBAL,
// maybe one day STB_WEAK.
- bind = (ver || (x->type & SHIDDEN)) ? STB_LOCAL : STB_GLOBAL;
+ bind = STB_GLOBAL;
+ if(ver || (x->type & SHIDDEN))
+ bind = STB_LOCAL;
+
+ // In external linking mode, we have to invoke gcc with -rdynamic
+ // to get the exported symbols put into the dynamic symbol table.
+ // To avoid filling the dynamic table with lots of unnecessary symbols,
+ // mark all Go symbols local (not global) in the final executable.
+ if(linkmode == LinkExternal && !(x->cgoexport&CgoExportStatic))
+ bind = STB_LOCAL;
+
if(bind != elfbind)
return;
off = putelfstr(s);
- if(isobj)
+ if(linkmode == LinkExternal)
addr -= xo->sect->vaddr;
putelfsyment(off, addr, size, (bind<<4)|(type&0xf), xo->sect->elfsect->shnum, (x->type & SHIDDEN) ? 2 : 0);
x->elfsym = numelfsym++;
@@ -424,10 +434,8 @@ symtab(void)
xdefine("datarelro", SDATARELRO, 0);
xdefine("edatarelro", SDATARELRO, 0);
}
- xdefine("gcdata", SGCDATA, 0);
- xdefine("egcdata", SGCDATA, 0);
- xdefine("gcbss", SGCBSS, 0);
- xdefine("egcbss", SGCBSS, 0);
+ xdefine("egcdata", STYPE, 0);
+ xdefine("egcbss", STYPE, 0);
xdefine("noptrdata", SNOPTRDATA, 0);
xdefine("enoptrdata", SNOPTRDATA, 0);
xdefine("data", SDATA, 0);
diff --git a/src/cmd/vet/Makefile b/src/cmd/vet/Makefile
index 307f4729c..45bd29170 100644
--- a/src/cmd/vet/Makefile
+++ b/src/cmd/vet/Makefile
@@ -2,7 +2,11 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
+# Assumes go/types is installed
test testshort:
- go build -tags vet_test
- ../../../test/errchk ./vet -compositewhitelist=false -printfuncs='Warn:1,Warnf:1' *.go
+ go build -tags 'vet_test gotypes'
+ ../../../test/errchk ./vet -printfuncs='Warn:1,Warnf:1' *.go *.s
+test_notypes:
+ go build -tags 'vet_test'
+ ../../../test/errchk ./vet -printfuncs='Warn:1,Warnf:1' *.go *.s
diff --git a/src/cmd/vet/asmdecl.go b/src/cmd/vet/asmdecl.go
new file mode 100644
index 000000000..2cfaa938f
--- /dev/null
+++ b/src/cmd/vet/asmdecl.go
@@ -0,0 +1,532 @@
+// Copyright 2013 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.
+
+// Identify mismatches between assembly files and Go func declarations.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/token"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+// 'kind' is a kind of assembly variable.
+// The kinds 1, 2, 4, 8 stand for values of that size.
+type asmKind int
+
+// These special kinds are not valid sizes.
+const (
+ asmString asmKind = 100 + iota
+ asmSlice
+ asmInterface
+ asmEmptyInterface
+)
+
+// An asmArch describes assembly parameters for an architecture
+type asmArch struct {
+ name string
+ ptrSize int
+ intSize int
+ bigEndian bool
+}
+
+// An asmFunc describes the expected variables for a function on a given architecture.
+type asmFunc struct {
+ arch *asmArch
+ size int // size of all arguments
+ vars map[string]*asmVar
+ varByOffset map[int]*asmVar
+}
+
+// An asmVar describes a single assembly variable.
+type asmVar struct {
+ name string
+ kind asmKind
+ typ string
+ off int
+ size int
+ inner []*asmVar
+}
+
+var (
+ asmArch386 = asmArch{"386", 4, 4, false}
+ asmArchArm = asmArch{"arm", 4, 4, false}
+ asmArchAmd64 = asmArch{"amd64", 8, 8, false}
+
+ arches = []*asmArch{
+ &asmArch386,
+ &asmArchArm,
+ &asmArchAmd64,
+ }
+)
+
+var (
+ re = regexp.MustCompile
+ asmPlusBuild = re(`//\s+\+build\s+([^\n]+)`)
+ asmTEXT = re(`\bTEXT\b.*·([^\(]+)\(SB\)(?:\s*,\s*([0-9]+))?(?:\s*,\s*\$([0-9]+)(?:-([0-9]+))?)?`)
+ asmDATA = re(`\b(DATA|GLOBL)\b`)
+ asmNamedFP = re(`([a-zA-Z0-9_\xFF-\x{10FFFF}]+)(?:\+([0-9]+))\(FP\)`)
+ asmUnnamedFP = re(`[^+\-0-9]](([0-9]+)\(FP\))`)
+ asmOpcode = re(`^\s*(?:[A-Z0-9a-z_]+:)?\s*([A-Z]+)\s*([^,]*)(?:,\s*(.*))?`)
+)
+
+func asmCheck(pkg *Package) {
+ if !vet("asmdecl") {
+ return
+ }
+
+ // No work if no assembly files.
+ if !pkg.hasFileWithSuffix(".s") {
+ return
+ }
+
+ // Gather declarations. knownFunc[name][arch] is func description.
+ knownFunc := make(map[string]map[string]*asmFunc)
+
+ for _, f := range pkg.files {
+ if f.file != nil {
+ for _, decl := range f.file.Decls {
+ if decl, ok := decl.(*ast.FuncDecl); ok && decl.Body == nil {
+ knownFunc[decl.Name.Name] = f.asmParseDecl(decl)
+ }
+ }
+ }
+ }
+
+ var fn *asmFunc
+ for _, f := range pkg.files {
+ if !strings.HasSuffix(f.name, ".s") {
+ continue
+ }
+
+ // Determine architecture from file name if possible.
+ var arch string
+ for _, a := range arches {
+ if strings.HasSuffix(f.name, "_"+a.name+".s") {
+ arch = a.name
+ break
+ }
+ }
+
+ lines := strings.SplitAfter(string(f.content), "\n")
+ for lineno, line := range lines {
+ lineno++
+
+ warnf := func(format string, args ...interface{}) {
+ f.Warnf(token.NoPos, "%s:%d: [%s] %s", f.name, lineno, arch, fmt.Sprintf(format, args...))
+ }
+
+ if arch == "" {
+ // Determine architecture from +build line if possible.
+ if m := asmPlusBuild.FindStringSubmatch(line); m != nil {
+ Fields:
+ for _, fld := range strings.Fields(m[1]) {
+ for _, a := range arches {
+ if a.name == fld {
+ arch = a.name
+ break Fields
+ }
+ }
+ }
+ }
+ }
+
+ if m := asmTEXT.FindStringSubmatch(line); m != nil {
+ if arch == "" {
+ f.Warnf(token.NoPos, "%s: cannot determine architecture for assembly file", f.name)
+ return
+ }
+ fn = knownFunc[m[1]][arch]
+ if fn != nil {
+ size, _ := strconv.Atoi(m[4])
+ if size != fn.size && (m[2] != "7" || size != 0) {
+ warnf("wrong argument size %d; expected $...-%d", size, fn.size)
+ }
+ }
+ continue
+ } else if strings.Contains(line, "TEXT") && strings.Contains(line, "SB") {
+ // function, but not visible from Go (didn't match asmTEXT), so stop checking
+ fn = nil
+ continue
+ }
+
+ if asmDATA.FindStringSubmatch(line) != nil {
+ fn = nil
+ }
+ if fn == nil {
+ continue
+ }
+
+ for _, m := range asmUnnamedFP.FindAllStringSubmatch(line, -1) {
+ warnf("use of unnamed argument %s", m[1])
+ }
+
+ for _, m := range asmNamedFP.FindAllStringSubmatch(line, -1) {
+ name := m[1]
+ off := 0
+ if m[2] != "" {
+ off, _ = strconv.Atoi(m[2])
+ }
+ v := fn.vars[name]
+ if v == nil {
+ // Allow argframe+0(FP).
+ if name == "argframe" && off == 0 {
+ continue
+ }
+ v = fn.varByOffset[off]
+ if v != nil {
+ warnf("unknown variable %s; offset %d is %s+%d(FP)", name, off, v.name, v.off)
+ } else {
+ warnf("unknown variable %s", name)
+ }
+ continue
+ }
+ asmCheckVar(warnf, fn, line, m[0], off, v)
+ }
+ }
+ }
+}
+
+// asmParseDecl parses a function decl for expected assembly variables.
+func (f *File) asmParseDecl(decl *ast.FuncDecl) map[string]*asmFunc {
+ var (
+ arch *asmArch
+ fn *asmFunc
+ offset int
+ failed bool
+ )
+
+ addVar := func(outer string, v asmVar) {
+ if vo := fn.vars[outer]; vo != nil {
+ vo.inner = append(vo.inner, &v)
+ }
+ fn.vars[v.name] = &v
+ for i := 0; i < v.size; i++ {
+ fn.varByOffset[v.off+i] = &v
+ }
+ }
+
+ addParams := func(list []*ast.Field) {
+ for i, fld := range list {
+ // Determine alignment, size, and kind of type in declaration.
+ var align, size int
+ var kind asmKind
+ names := fld.Names
+ typ := f.gofmt(fld.Type)
+ switch t := fld.Type.(type) {
+ default:
+ switch typ {
+ default:
+ f.Warnf(fld.Type.Pos(), "unknown assembly argument type %s", typ)
+ failed = true
+ return
+ case "int8", "uint8", "byte", "bool":
+ size = 1
+ case "int16", "uint16":
+ size = 2
+ case "int32", "uint32", "float32":
+ size = 4
+ case "int64", "uint64", "float64":
+ align = arch.ptrSize
+ size = 8
+ case "int", "uint":
+ size = arch.intSize
+ case "uintptr", "iword", "Word", "Errno", "unsafe.Pointer":
+ size = arch.ptrSize
+ case "string":
+ size = arch.ptrSize * 2
+ align = arch.ptrSize
+ kind = asmString
+ }
+ case *ast.ChanType, *ast.FuncType, *ast.MapType, *ast.StarExpr:
+ size = arch.ptrSize
+ case *ast.InterfaceType:
+ align = arch.ptrSize
+ size = 2 * arch.ptrSize
+ if len(t.Methods.List) > 0 {
+ kind = asmInterface
+ } else {
+ kind = asmEmptyInterface
+ }
+ case *ast.ArrayType:
+ if t.Len == nil {
+ size = arch.ptrSize + 2*arch.intSize
+ align = arch.ptrSize
+ kind = asmSlice
+ break
+ }
+ f.Warnf(fld.Type.Pos(), "unsupported assembly argument type %s", typ)
+ failed = true
+ case *ast.StructType:
+ f.Warnf(fld.Type.Pos(), "unsupported assembly argument type %s", typ)
+ failed = true
+ }
+ if align == 0 {
+ align = size
+ }
+ if kind == 0 {
+ kind = asmKind(size)
+ }
+ offset += -offset & (align - 1)
+
+ // Create variable for each name being declared with this type.
+ if len(names) == 0 {
+ name := "unnamed"
+ if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 && &list[0] == &decl.Type.Results.List[0] && i == 0 {
+ // Assume assembly will refer to single unnamed result as r.
+ name = "ret"
+ }
+ names = []*ast.Ident{{Name: name}}
+ }
+ for _, id := range names {
+ name := id.Name
+ addVar("", asmVar{
+ name: name,
+ kind: kind,
+ typ: typ,
+ off: offset,
+ size: size,
+ })
+ switch kind {
+ case 8:
+ if arch.ptrSize == 4 {
+ w1, w2 := "lo", "hi"
+ if arch.bigEndian {
+ w1, w2 = w2, w1
+ }
+ addVar(name, asmVar{
+ name: name + "_" + w1,
+ kind: 4,
+ typ: "half " + typ,
+ off: offset,
+ size: 4,
+ })
+ addVar(name, asmVar{
+ name: name + "_" + w2,
+ kind: 4,
+ typ: "half " + typ,
+ off: offset + 4,
+ size: 4,
+ })
+ }
+
+ case asmEmptyInterface:
+ addVar(name, asmVar{
+ name: name + "_type",
+ kind: asmKind(arch.ptrSize),
+ typ: "interface type",
+ off: offset,
+ size: arch.ptrSize,
+ })
+ addVar(name, asmVar{
+ name: name + "_data",
+ kind: asmKind(arch.ptrSize),
+ typ: "interface data",
+ off: offset + arch.ptrSize,
+ size: arch.ptrSize,
+ })
+
+ case asmInterface:
+ addVar(name, asmVar{
+ name: name + "_itable",
+ kind: asmKind(arch.ptrSize),
+ typ: "interface itable",
+ off: offset,
+ size: arch.ptrSize,
+ })
+ addVar(name, asmVar{
+ name: name + "_data",
+ kind: asmKind(arch.ptrSize),
+ typ: "interface data",
+ off: offset + arch.ptrSize,
+ size: arch.ptrSize,
+ })
+
+ case asmSlice:
+ addVar(name, asmVar{
+ name: name + "_base",
+ kind: asmKind(arch.ptrSize),
+ typ: "slice base",
+ off: offset,
+ size: arch.ptrSize,
+ })
+ addVar(name, asmVar{
+ name: name + "_len",
+ kind: asmKind(arch.intSize),
+ typ: "slice len",
+ off: offset + arch.ptrSize,
+ size: arch.intSize,
+ })
+ addVar(name, asmVar{
+ name: name + "_cap",
+ kind: asmKind(arch.intSize),
+ typ: "slice cap",
+ off: offset + arch.ptrSize + arch.intSize,
+ size: arch.intSize,
+ })
+
+ case asmString:
+ addVar(name, asmVar{
+ name: name + "_base",
+ kind: asmKind(arch.ptrSize),
+ typ: "string base",
+ off: offset,
+ size: arch.ptrSize,
+ })
+ addVar(name, asmVar{
+ name: name + "_len",
+ kind: asmKind(arch.intSize),
+ typ: "string len",
+ off: offset + arch.ptrSize,
+ size: arch.intSize,
+ })
+ }
+ offset += size
+ }
+ }
+ }
+
+ m := make(map[string]*asmFunc)
+ for _, arch = range arches {
+ fn = &asmFunc{
+ arch: arch,
+ vars: make(map[string]*asmVar),
+ varByOffset: make(map[int]*asmVar),
+ }
+ offset = 0
+ addParams(decl.Type.Params.List)
+ if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 {
+ offset += -offset & (arch.ptrSize - 1)
+ addParams(decl.Type.Results.List)
+ }
+ fn.size = offset
+ m[arch.name] = fn
+ }
+
+ if failed {
+ return nil
+ }
+ return m
+}
+
+// asmCheckVar checks a single variable reference.
+func asmCheckVar(warnf func(string, ...interface{}), fn *asmFunc, line, expr string, off int, v *asmVar) {
+ m := asmOpcode.FindStringSubmatch(line)
+ if m == nil {
+ warnf("cannot find assembly opcode")
+ }
+
+ // Determine operand sizes from instruction.
+ // Typically the suffix suffices, but there are exceptions.
+ var src, dst, kind asmKind
+ op := m[1]
+ switch fn.arch.name + "." + op {
+ case "386.FMOVLP":
+ src, dst = 8, 4
+ case "arm.MOVD":
+ src = 8
+ case "arm.MOVW":
+ src = 4
+ case "arm.MOVH", "arm.MOVHU":
+ src = 2
+ case "arm.MOVB", "arm.MOVBU":
+ src = 1
+ default:
+ if fn.arch.name == "386" || fn.arch.name == "amd64" {
+ if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "D") || strings.HasSuffix(op, "DP")) {
+ // FMOVDP, FXCHD, etc
+ src = 8
+ break
+ }
+ if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "F") || strings.HasSuffix(op, "FP")) {
+ // FMOVFP, FXCHF, etc
+ src = 4
+ break
+ }
+ if strings.HasSuffix(op, "SD") {
+ // MOVSD, SQRTSD, etc
+ src = 8
+ break
+ }
+ if strings.HasSuffix(op, "SS") {
+ // MOVSS, SQRTSS, etc
+ src = 4
+ break
+ }
+ if strings.HasPrefix(op, "SET") {
+ // SETEQ, etc
+ src = 1
+ break
+ }
+ switch op[len(op)-1] {
+ case 'B':
+ src = 1
+ case 'W':
+ src = 2
+ case 'L':
+ src = 4
+ case 'D', 'Q':
+ src = 8
+ }
+ }
+ }
+ if dst == 0 {
+ dst = src
+ }
+
+ // Determine whether the match we're holding
+ // is the first or second argument.
+ if strings.Index(line, expr) > strings.Index(line, ",") {
+ kind = dst
+ } else {
+ kind = src
+ }
+
+ vk := v.kind
+ vt := v.typ
+ switch vk {
+ case asmInterface, asmEmptyInterface, asmString, asmSlice:
+ // allow reference to first word (pointer)
+ vk = v.inner[0].kind
+ vt = v.inner[0].typ
+ }
+
+ if off != v.off {
+ var inner bytes.Buffer
+ for i, vi := range v.inner {
+ if len(v.inner) > 1 {
+ fmt.Fprintf(&inner, ",")
+ }
+ fmt.Fprintf(&inner, " ")
+ if i == len(v.inner)-1 {
+ fmt.Fprintf(&inner, "or ")
+ }
+ fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
+ }
+ warnf("invalid offset %s; expected %s+%d(FP)%s", expr, v.name, v.off, inner.String())
+ return
+ }
+ if kind != 0 && kind != vk {
+ var inner bytes.Buffer
+ if len(v.inner) > 0 {
+ fmt.Fprintf(&inner, " containing")
+ for i, vi := range v.inner {
+ if i > 0 && len(v.inner) > 2 {
+ fmt.Fprintf(&inner, ",")
+ }
+ fmt.Fprintf(&inner, " ")
+ if i > 0 && i == len(v.inner)-1 {
+ fmt.Fprintf(&inner, "and ")
+ }
+ fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
+ }
+ }
+ warnf("invalid %s of %s; %s is %d-byte value%s", op, expr, vt, vk, inner.String())
+ }
+}
diff --git a/src/cmd/vet/assign.go b/src/cmd/vet/assign.go
new file mode 100644
index 000000000..a11f0f875
--- /dev/null
+++ b/src/cmd/vet/assign.go
@@ -0,0 +1,44 @@
+// Copyright 2013 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.
+
+/*
+This file contains the code to check for useless assignments.
+*/
+
+package main
+
+import (
+ "go/ast"
+ "go/token"
+ "reflect"
+)
+
+// TODO: should also check for assignments to struct fields inside methods
+// that are on T instead of *T.
+
+// checkAssignStmt checks for assignments of the form "<expr> = <expr>".
+// These are almost always useless, and even when they aren't they are usually a mistake.
+func (f *File) checkAssignStmt(stmt *ast.AssignStmt) {
+ if !vet("assign") {
+ return
+ }
+ if stmt.Tok != token.ASSIGN {
+ return // ignore :=
+ }
+ if len(stmt.Lhs) != len(stmt.Rhs) {
+ // If LHS and RHS have different cardinality, they can't be the same.
+ return
+ }
+ for i, lhs := range stmt.Lhs {
+ rhs := stmt.Rhs[i]
+ if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) {
+ continue // short-circuit the heavy-weight gofmt check
+ }
+ le := f.gofmt(lhs)
+ re := f.gofmt(rhs)
+ if le == re {
+ f.Warnf(stmt.Pos(), "self-assignment of %s to %s", re, le)
+ }
+ }
+}
diff --git a/src/cmd/vet/buildtag.go b/src/cmd/vet/buildtag.go
index 4b7580457..0ab13cb8a 100644
--- a/src/cmd/vet/buildtag.go
+++ b/src/cmd/vet/buildtag.go
@@ -72,7 +72,7 @@ func checkBuildTag(name string, data []byte) {
elem = elem[1:]
}
for _, c := range elem {
- if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' {
+ if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
fmt.Fprintf(os.Stderr, "%s:%d: invalid non-alphanumeric build constraint: %s\n", name, i+1, arg)
setExit(1)
break Args
diff --git a/src/cmd/vet/deadcode.go b/src/cmd/vet/deadcode.go
new file mode 100644
index 000000000..f90fc14a4
--- /dev/null
+++ b/src/cmd/vet/deadcode.go
@@ -0,0 +1,280 @@
+// Copyright 2013 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.
+
+// Check for syntactically unreachable code.
+
+package main
+
+import (
+ "go/ast"
+ "go/token"
+)
+
+type deadState struct {
+ f *File
+ hasBreak map[ast.Stmt]bool
+ hasGoto map[string]bool
+ labels map[string]ast.Stmt
+ breakTarget ast.Stmt
+
+ reachable bool
+}
+
+// checkUnreachable checks a function body for dead code.
+func (f *File) checkUnreachable(body *ast.BlockStmt) {
+ if !vet("unreachable") || body == nil {
+ return
+ }
+
+ d := &deadState{
+ f: f,
+ hasBreak: make(map[ast.Stmt]bool),
+ hasGoto: make(map[string]bool),
+ labels: make(map[string]ast.Stmt),
+ }
+
+ d.findLabels(body)
+
+ d.reachable = true
+ d.findDead(body)
+}
+
+// findLabels gathers information about the labels defined and used by stmt
+// and about which statements break, whether a label is involved or not.
+func (d *deadState) findLabels(stmt ast.Stmt) {
+ switch x := stmt.(type) {
+ default:
+ d.f.Warnf(x.Pos(), "internal error in findLabels: unexpected statement %T", x)
+
+ case *ast.AssignStmt,
+ *ast.BadStmt,
+ *ast.DeclStmt,
+ *ast.DeferStmt,
+ *ast.EmptyStmt,
+ *ast.ExprStmt,
+ *ast.GoStmt,
+ *ast.IncDecStmt,
+ *ast.ReturnStmt,
+ *ast.SendStmt:
+ // no statements inside
+
+ case *ast.BlockStmt:
+ for _, stmt := range x.List {
+ d.findLabels(stmt)
+ }
+
+ case *ast.BranchStmt:
+ switch x.Tok {
+ case token.GOTO:
+ d.hasGoto[x.Label.Name] = true
+
+ case token.BREAK:
+ stmt := d.breakTarget
+ if x.Label != nil {
+ stmt = d.labels[x.Label.Name]
+ }
+ if stmt != nil {
+ d.hasBreak[stmt] = true
+ }
+ }
+
+ case *ast.IfStmt:
+ d.findLabels(x.Body)
+ if x.Else != nil {
+ d.findLabels(x.Else)
+ }
+
+ case *ast.LabeledStmt:
+ d.labels[x.Label.Name] = x.Stmt
+ d.findLabels(x.Stmt)
+
+ // These cases are all the same, but the x.Body only works
+ // when the specific type of x is known, so the cases cannot
+ // be merged.
+ case *ast.ForStmt:
+ outer := d.breakTarget
+ d.breakTarget = x
+ d.findLabels(x.Body)
+ d.breakTarget = outer
+
+ case *ast.RangeStmt:
+ outer := d.breakTarget
+ d.breakTarget = x
+ d.findLabels(x.Body)
+ d.breakTarget = outer
+
+ case *ast.SelectStmt:
+ outer := d.breakTarget
+ d.breakTarget = x
+ d.findLabels(x.Body)
+ d.breakTarget = outer
+
+ case *ast.SwitchStmt:
+ outer := d.breakTarget
+ d.breakTarget = x
+ d.findLabels(x.Body)
+ d.breakTarget = outer
+
+ case *ast.TypeSwitchStmt:
+ outer := d.breakTarget
+ d.breakTarget = x
+ d.findLabels(x.Body)
+ d.breakTarget = outer
+
+ case *ast.CommClause:
+ for _, stmt := range x.Body {
+ d.findLabels(stmt)
+ }
+
+ case *ast.CaseClause:
+ for _, stmt := range x.Body {
+ d.findLabels(stmt)
+ }
+ }
+}
+
+// findDead walks the statement looking for dead code.
+// If d.reachable is false on entry, stmt itself is dead.
+// When findDead returns, d.reachable tells whether the
+// statement following stmt is reachable.
+func (d *deadState) findDead(stmt ast.Stmt) {
+ // Is this a labeled goto target?
+ // If so, assume it is reachable due to the goto.
+ // This is slightly conservative, in that we don't
+ // check that the goto is reachable, so
+ // L: goto L
+ // will not provoke a warning.
+ // But it's good enough.
+ if x, isLabel := stmt.(*ast.LabeledStmt); isLabel && d.hasGoto[x.Label.Name] {
+ d.reachable = true
+ }
+
+ if !d.reachable {
+ switch stmt.(type) {
+ case *ast.EmptyStmt:
+ // do not warn about unreachable empty statements
+ default:
+ d.f.Warnf(stmt.Pos(), "unreachable code")
+ d.reachable = true // silence error about next statement
+ }
+ }
+
+ switch x := stmt.(type) {
+ default:
+ d.f.Warnf(x.Pos(), "internal error in findDead: unexpected statement %T", x)
+
+ case *ast.AssignStmt,
+ *ast.BadStmt,
+ *ast.DeclStmt,
+ *ast.DeferStmt,
+ *ast.EmptyStmt,
+ *ast.GoStmt,
+ *ast.IncDecStmt,
+ *ast.SendStmt:
+ // no control flow
+
+ case *ast.BlockStmt:
+ for _, stmt := range x.List {
+ d.findDead(stmt)
+ }
+
+ case *ast.BranchStmt:
+ switch x.Tok {
+ case token.BREAK, token.GOTO, token.FALLTHROUGH:
+ d.reachable = false
+ case token.CONTINUE:
+ // NOTE: We accept "continue" statements as terminating.
+ // They are not necessary in the spec definition of terminating,
+ // because a continue statement cannot be the final statement
+ // before a return. But for the more general problem of syntactically
+ // identifying dead code, continue redirects control flow just
+ // like the other terminating statements.
+ d.reachable = false
+ }
+
+ case *ast.ExprStmt:
+ // Call to panic?
+ call, ok := x.X.(*ast.CallExpr)
+ if ok {
+ name, ok := call.Fun.(*ast.Ident)
+ if ok && name.Name == "panic" && name.Obj == nil {
+ d.reachable = false
+ }
+ }
+
+ case *ast.ForStmt:
+ d.findDead(x.Body)
+ d.reachable = x.Cond != nil || d.hasBreak[x]
+
+ case *ast.IfStmt:
+ d.findDead(x.Body)
+ if x.Else != nil {
+ r := d.reachable
+ d.reachable = true
+ d.findDead(x.Else)
+ d.reachable = d.reachable || r
+ } else {
+ // might not have executed if statement
+ d.reachable = true
+ }
+
+ case *ast.LabeledStmt:
+ d.findDead(x.Stmt)
+
+ case *ast.RangeStmt:
+ d.findDead(x.Body)
+ d.reachable = true
+
+ case *ast.ReturnStmt:
+ d.reachable = false
+
+ case *ast.SelectStmt:
+ // NOTE: Unlike switch and type switch below, we don't care
+ // whether a select has a default, because a select without a
+ // default blocks until one of the cases can run. That's different
+ // from a switch without a default, which behaves like it has
+ // a default with an empty body.
+ anyReachable := false
+ for _, comm := range x.Body.List {
+ d.reachable = true
+ for _, stmt := range comm.(*ast.CommClause).Body {
+ d.findDead(stmt)
+ }
+ anyReachable = anyReachable || d.reachable
+ }
+ d.reachable = anyReachable || d.hasBreak[x]
+
+ case *ast.SwitchStmt:
+ anyReachable := false
+ hasDefault := false
+ for _, cas := range x.Body.List {
+ cc := cas.(*ast.CaseClause)
+ if cc.List == nil {
+ hasDefault = true
+ }
+ d.reachable = true
+ for _, stmt := range cc.Body {
+ d.findDead(stmt)
+ }
+ anyReachable = anyReachable || d.reachable
+ }
+ d.reachable = anyReachable || d.hasBreak[x] || !hasDefault
+
+ case *ast.TypeSwitchStmt:
+ anyReachable := false
+ hasDefault := false
+ for _, cas := range x.Body.List {
+ cc := cas.(*ast.CaseClause)
+ if cc.List == nil {
+ hasDefault = true
+ }
+ d.reachable = true
+ for _, stmt := range cc.Body {
+ d.findDead(stmt)
+ }
+ anyReachable = anyReachable || d.reachable
+ }
+ d.reachable = anyReachable || d.hasBreak[x] || !hasDefault
+ }
+}
diff --git a/src/cmd/vet/doc.go b/src/cmd/vet/doc.go
index f164eaca2..eb1e436f0 100644
--- a/src/cmd/vet/doc.go
+++ b/src/cmd/vet/doc.go
@@ -9,6 +9,12 @@ calls whose arguments do not align with the format string. Vet uses heuristics
that do not guarantee all reports are genuine problems, but it can find errors
not caught by the compilers.
+Its exit code is 2 for erroneous invocation of the tool, 1 if a
+problem was reported, and 0 otherwise. Note that the tool does not
+check every possible problem and depends on unreliable heuristics
+so it should be used as guidance only, not as a firm indicator of
+program correctness.
+
By default all checks are performed, but if explicit flags are provided, only
those identified by the flags are performed.
diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go
index 20f6cca1a..2fefa0b47 100644
--- a/src/cmd/vet/main.go
+++ b/src/cmd/vet/main.go
@@ -15,7 +15,6 @@ import (
"go/parser"
"go/printer"
"go/token"
- "go/types"
"io/ioutil"
"os"
"path/filepath"
@@ -29,14 +28,17 @@ var exitCode = 0
// Flags to control which checks to perform. "all" is set to true here, and disabled later if
// a flag is set explicitly.
var report = map[string]*bool{
- "all": flag.Bool("all", true, "check everything; disabled if any explicit check is requested"),
- "atomic": flag.Bool("atomic", false, "check for common mistaken usages of the sync/atomic package"),
- "buildtags": flag.Bool("buildtags", false, "check that +build tags are valid"),
- "composites": flag.Bool("composites", false, "check that composite literals used type-tagged elements"),
- "methods": flag.Bool("methods", false, "check that canonically named methods are canonically defined"),
- "printf": flag.Bool("printf", false, "check printf-like invocations"),
- "structtags": flag.Bool("structtags", false, "check that struct field tags have canonical format"),
- "rangeloops": flag.Bool("rangeloops", false, "check that range loop variables are used correctly"),
+ "all": flag.Bool("all", true, "check everything; disabled if any explicit check is requested"),
+ "asmdecl": flag.Bool("asmdecl", false, "check assembly against Go declarations"),
+ "assign": flag.Bool("assign", false, "check for useless assignments"),
+ "atomic": flag.Bool("atomic", false, "check for common mistaken usages of the sync/atomic package"),
+ "buildtags": flag.Bool("buildtags", false, "check that +build tags are valid"),
+ "composites": flag.Bool("composites", false, "check that composite literals used type-tagged elements"),
+ "methods": flag.Bool("methods", false, "check that canonically named methods are canonically defined"),
+ "printf": flag.Bool("printf", false, "check printf-like invocations"),
+ "rangeloops": flag.Bool("rangeloops", false, "check that range loop variables are used correctly"),
+ "structtags": flag.Bool("structtags", false, "check that struct field tags have canonical format"),
+ "unreachable": flag.Bool("unreachable", false, "check for unreachable code"),
}
// vet tells whether to report errors for the named check, a flag name.
@@ -64,11 +66,12 @@ func Usage() {
// File is a wrapper for the state of a file used in the parser.
// The parse tree walkers are all methods of this type.
type File struct {
- pkg *Package
- fset *token.FileSet
- name string
- file *ast.File
- b bytes.Buffer // for use by methods
+ pkg *Package
+ fset *token.FileSet
+ name string
+ content []byte
+ file *ast.File
+ b bytes.Buffer // for use by methods
}
func main() {
@@ -163,6 +166,7 @@ func doPackageDir(directory string) {
names = append(names, pkg.GoFiles...)
names = append(names, pkg.CgoFiles...)
names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
+ names = append(names, pkg.SFiles...)
prefixDirectory(directory, names)
doPackage(names)
// Is there also a "foo_test" package? If so, do that one as well.
@@ -174,8 +178,9 @@ func doPackageDir(directory string) {
}
type Package struct {
- types map[ast.Expr]types.Type
+ types map[ast.Expr]Type
values map[ast.Expr]interface{}
+ files []*File
}
// doPackage analyzes the single package constructed from the named files.
@@ -186,50 +191,48 @@ func doPackage(names []string) {
for _, name := range names {
f, err := os.Open(name)
if err != nil {
- errorf("%s: %s", name, err)
+ // Warn but continue to next package.
+ warnf("%s: %s", name, err)
+ return
}
defer f.Close()
data, err := ioutil.ReadAll(f)
if err != nil {
- errorf("%s: %s", name, err)
+ warnf("%s: %s", name, err)
+ return
}
checkBuildTag(name, data)
- parsedFile, err := parser.ParseFile(fs, name, bytes.NewReader(data), 0)
- if err != nil {
- errorf("%s: %s", name, err)
+ var parsedFile *ast.File
+ if strings.HasSuffix(name, ".go") {
+ parsedFile, err = parser.ParseFile(fs, name, bytes.NewReader(data), 0)
+ if err != nil {
+ warnf("%s: %s", name, err)
+ return
+ }
+ astFiles = append(astFiles, parsedFile)
}
- files = append(files, &File{fset: fs, name: name, file: parsedFile})
- astFiles = append(astFiles, parsedFile)
+ files = append(files, &File{fset: fs, content: data, name: name, file: parsedFile})
}
pkg := new(Package)
- pkg.types = make(map[ast.Expr]types.Type)
- pkg.values = make(map[ast.Expr]interface{})
- exprFn := func(x ast.Expr, typ types.Type, val interface{}) {
- pkg.types[x] = typ
- if val != nil {
- pkg.values[x] = val
- }
- }
- // By providing the Context with our own error function, it will continue
- // past the first error. There is no need for that function to do anything.
- context := types.Context{
- Expr: exprFn,
- Error: func(error) {},
- }
+ pkg.files = files
// Type check the package.
- _, err := context.Check(fs, astFiles)
+ err := pkg.check(fs, astFiles)
if err != nil && *verbose {
warnf("%s", err)
}
for _, file := range files {
file.pkg = pkg
- file.walkFile(file.name, file.file)
+ if file.file != nil {
+ file.walkFile(file.name, file.file)
+ }
}
+ asmCheck(pkg)
}
func visit(path string, f os.FileInfo, err error) error {
if err != nil {
- errorf("walk error: %s", err)
+ warnf("walk error: %s", err)
+ return err
}
// One package per directory. Ignore the files themselves.
if !f.IsDir() {
@@ -239,7 +242,16 @@ func visit(path string, f os.FileInfo, err error) error {
return nil
}
-// walkDir recursively walks the tree looking for .go files.
+func (pkg *Package) hasFileWithSuffix(suffix string) bool {
+ for _, f := range pkg.files {
+ if strings.HasSuffix(f.name, suffix) {
+ return true
+ }
+ }
+ return false
+}
+
+// walkDir recursively walks the tree looking for Go packages.
func walkDir(root string) {
filepath.Walk(root, visit)
}
@@ -287,6 +299,9 @@ func (f *File) Badf(pos token.Pos, format string, args ...interface{}) {
}
func (f *File) loc(pos token.Pos) string {
+ if pos == token.NoPos {
+ return ""
+ }
// Do not print columns. Because the pos often points to the start of an
// expression instead of the inner part with the actual error, the
// precision can mislead.
@@ -322,7 +337,9 @@ func (f *File) Visit(node ast.Node) ast.Visitor {
case *ast.Field:
f.walkFieldTag(n)
case *ast.FuncDecl:
- f.walkMethodDecl(n)
+ f.walkFuncDecl(n)
+ case *ast.FuncLit:
+ f.walkFuncLit(n)
case *ast.InterfaceType:
f.walkInterfaceType(n)
case *ast.RangeStmt:
@@ -333,6 +350,7 @@ func (f *File) Visit(node ast.Node) ast.Visitor {
// walkAssignStmt walks an assignment statement
func (f *File) walkAssignStmt(stmt *ast.AssignStmt) {
+ f.checkAssignStmt(stmt)
f.checkAtomicAssignment(stmt)
}
@@ -364,18 +382,22 @@ func (f *File) walkFieldTag(field *ast.Field) {
f.checkCanonicalFieldTag(field)
}
-// walkMethodDecl walks the method's signature.
+// walkMethod walks the method's signature.
func (f *File) walkMethod(id *ast.Ident, t *ast.FuncType) {
f.checkCanonicalMethod(id, t)
}
-// walkMethodDecl walks the method signature in the declaration.
-func (f *File) walkMethodDecl(d *ast.FuncDecl) {
- if d.Recv == nil {
- // not a method
- return
+// walkFuncDecl walks a function declaration.
+func (f *File) walkFuncDecl(d *ast.FuncDecl) {
+ f.checkUnreachable(d.Body)
+ if d.Recv != nil {
+ f.walkMethod(d.Name, d.Type)
}
- f.walkMethod(d.Name, d.Type)
+}
+
+// walkFuncLit walks a function literal.
+func (f *File) walkFuncLit(x *ast.FuncLit) {
+ f.checkUnreachable(x.Body)
}
// walkInterfaceType walks the method signatures of an interface.
diff --git a/src/cmd/vet/method.go b/src/cmd/vet/method.go
index bf982dc7a..8064235f4 100644
--- a/src/cmd/vet/method.go
+++ b/src/cmd/vet/method.go
@@ -93,7 +93,7 @@ func (f *File) checkCanonicalMethod(id *ast.Ident, t *ast.FuncType) {
actual = strings.TrimPrefix(actual, "func")
actual = id.Name + actual
- f.Warnf(id.Pos(), "method %s should have signature %s", actual, expectFmt)
+ f.Badf(id.Pos(), "method %s should have signature %s", actual, expectFmt)
}
}
diff --git a/src/cmd/vet/print.go b/src/cmd/vet/print.go
index fb0fb9f9b..debfbf0bf 100644
--- a/src/cmd/vet/print.go
+++ b/src/cmd/vet/print.go
@@ -10,7 +10,6 @@ import (
"flag"
"go/ast"
"go/token"
- "go/types"
"strconv"
"strings"
"unicode/utf8"
@@ -302,59 +301,6 @@ func (f *File) checkPrintfArg(call *ast.CallExpr, verb rune, flags []byte, argNu
f.Badf(call.Pos(), "unrecognized printf verb %q", verb)
}
-func (f *File) matchArgType(t printfArgType, arg ast.Expr) bool {
- // TODO: for now, we can only test builtin types and untyped constants.
- typ := f.pkg.types[arg]
- if typ == nil {
- return true
- }
- basic, ok := typ.(*types.Basic)
- if !ok {
- return true
- }
- switch basic.Kind {
- case types.Bool:
- return t&argBool != 0
- case types.Int, types.Int8, types.Int16, types.Int32, types.Int64:
- fallthrough
- case types.Uint, types.Uint8, types.Uint16, types.Uint32, types.Uint64, types.Uintptr:
- return t&argInt != 0
- case types.Float32, types.Float64, types.Complex64, types.Complex128:
- return t&argFloat != 0
- case types.String:
- return t&argString != 0
- case types.UnsafePointer:
- return t&(argPointer|argInt) != 0
- case types.UntypedBool:
- return t&argBool != 0
- case types.UntypedComplex:
- return t&argFloat != 0
- case types.UntypedFloat:
- // If it's integral, we can use an int format.
- switch f.pkg.values[arg].(type) {
- case int, int8, int16, int32, int64:
- return t&(argInt|argFloat) != 0
- case uint, uint8, uint16, uint32, uint64:
- return t&(argInt|argFloat) != 0
- }
- return t&argFloat != 0
- case types.UntypedInt:
- return t&argInt != 0
- case types.UntypedRune:
- return t&(argInt|argRune) != 0
- case types.UntypedString:
- return t&argString != 0
- case types.UntypedNil:
- return t&argPointer != 0 // TODO?
- case types.Invalid:
- if *verbose {
- f.Warnf(arg.Pos(), "printf argument %v has invalid or unknown type", arg)
- }
- return true // Probably a type check problem.
- }
- return false
-}
-
// checkPrint checks a call to an unformatted print routine such as Println.
// call.Args[firstArg] is the first argument to be printed.
func (f *File) checkPrint(call *ast.CallExpr, name string, firstArg int) {
@@ -366,7 +312,7 @@ func (f *File) checkPrint(call *ast.CallExpr, name string, firstArg int) {
if sel, ok := args[0].(*ast.SelectorExpr); ok {
if x, ok := sel.X.(*ast.Ident); ok {
if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
- f.Warnf(call.Pos(), "first argument to %s is %s.%s", name, x.Name, sel.Sel.Name)
+ f.Badf(call.Pos(), "first argument to %s is %s.%s", name, x.Name, sel.Sel.Name)
}
}
}
@@ -403,64 +349,3 @@ func (f *File) checkPrint(call *ast.CallExpr, name string, firstArg int) {
}
}
}
-
-// numArgsInSignature tells how many formal arguments the function type
-// being called has.
-func (f *File) numArgsInSignature(call *ast.CallExpr) int {
- // Check the type of the function or method declaration
- typ := f.pkg.types[call.Fun]
- if typ == nil {
- return 0
- }
- // The type must be a signature, but be sure for safety.
- sig, ok := typ.(*types.Signature)
- if !ok {
- return 0
- }
- return len(sig.Params)
-}
-
-// isErrorMethodCall reports whether the call is of a method with signature
-// func Error() string
-// where "string" is the universe's string type. We know the method is called "Error".
-func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
- // Is it a selector expression? Otherwise it's a function call, not a method call.
- sel, ok := call.Fun.(*ast.SelectorExpr)
- if !ok {
- return false
- }
- // The package is type-checked, so if there are no arguments, we're done.
- if len(call.Args) > 0 {
- return false
- }
- // Check the type of the method declaration
- typ := f.pkg.types[sel]
- if typ == nil {
- return false
- }
- // The type must be a signature, but be sure for safety.
- sig, ok := typ.(*types.Signature)
- if !ok {
- return false
- }
- // There must be a receiver for it to be a method call. Otherwise it is
- // a function, not something that satisfies the error interface.
- if sig.Recv == nil {
- return false
- }
- // There must be no arguments. Already verified by type checking, but be thorough.
- if len(sig.Params) > 0 {
- return false
- }
- // Finally the real questions.
- // There must be one result.
- if len(sig.Results) != 1 {
- return false
- }
- // It must have return type "string" from the universe.
- result := sig.Results[0].Type
- if types.IsIdentical(result, types.Typ[types.String]) {
- return true
- }
- return false
-}
diff --git a/src/cmd/vet/structtag.go b/src/cmd/vet/structtag.go
index 545e420c1..d83578836 100644
--- a/src/cmd/vet/structtag.go
+++ b/src/cmd/vet/structtag.go
@@ -23,7 +23,7 @@ func (f *File) checkCanonicalFieldTag(field *ast.Field) {
tag, err := strconv.Unquote(field.Tag.Value)
if err != nil {
- f.Warnf(field.Pos(), "unable to read struct tag %s", field.Tag.Value)
+ f.Badf(field.Pos(), "unable to read struct tag %s", field.Tag.Value)
return
}
@@ -31,7 +31,7 @@ func (f *File) checkCanonicalFieldTag(field *ast.Field) {
// new key:value to end and checking that
// the tag parsing code can find it.
if reflect.StructTag(tag+` _gofix:"_magic"`).Get("_gofix") != "_magic" {
- f.Warnf(field.Pos(), "struct field tag %s not compatible with reflect.StructTag.Get", field.Tag.Value)
+ f.Badf(field.Pos(), "struct field tag %s not compatible with reflect.StructTag.Get", field.Tag.Value)
return
}
}
diff --git a/src/cmd/vet/taglit.go b/src/cmd/vet/taglit.go
index 0324e37b0..bcad2fe0a 100644
--- a/src/cmd/vet/taglit.go
+++ b/src/cmd/vet/taglit.go
@@ -9,32 +9,52 @@ package main
import (
"flag"
"go/ast"
- "go/types"
"strings"
)
var compositeWhiteList = flag.Bool("compositewhitelist", true, "use composite white list; for testing only")
-// checkUntaggedLiteral checks if a composite literal is an struct literal with
+// checkUntaggedLiteral checks if a composite literal is a struct literal with
// untagged fields.
func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
if !vet("composites") {
return
}
- // Check that the CompositeLit's type is a slice or array (which needs no tag), if possible.
- typ := f.pkg.types[c]
- if typ != nil {
- // If it's a named type, pull out the underlying type.
- if namedType, ok := typ.(*types.NamedType); ok {
- typ = namedType.Underlying
- }
- switch typ.(type) {
- case *types.Slice:
- return
- case *types.Array:
- return
+ typ := c.Type
+ for {
+ if typ1, ok := c.Type.(*ast.ParenExpr); ok {
+ typ = typ1
+ continue
}
+ break
+ }
+
+ switch typ.(type) {
+ case *ast.ArrayType:
+ return
+ case *ast.MapType:
+ return
+ case *ast.StructType:
+ return // a literal struct type does not need to use tags
+ case *ast.Ident:
+ // A simple type name like t or T does not need tags either,
+ // since it is almost certainly declared in the current package.
+ // (The exception is names being used via import . "pkg", but
+ // those are already breaking the Go 1 compatibility promise,
+ // so not reporting potential additional breakage seems okay.)
+ return
+ }
+
+ // Otherwise the type is a selector like pkg.Name.
+ // We only care if pkg.Name is a struct, not if it's a map, array, or slice.
+ isStruct, typeString := f.pkg.isStruct(c)
+ if !isStruct {
+ return
+ }
+
+ if typeString == "" { // isStruct doesn't know
+ typeString = f.gofmt(typ)
}
// It's a struct, or we can't tell it's not a struct because we don't have types.
@@ -64,7 +84,7 @@ func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
// Convert the package name to an import path, and compare to a whitelist.
path := pkgPath(f, pkg.Name)
if path == "" {
- f.Warnf(c.Pos(), "unresolvable package for %s.%s literal", pkg.Name, s.Sel.Name)
+ f.Badf(c.Pos(), "unresolvable package for %s.%s literal", pkg.Name, s.Sel.Name)
return
}
typeName := path + "." + s.Sel.Name
@@ -72,7 +92,7 @@ func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
return
}
- f.Warnf(c.Pos(), "%s composite literal uses untagged fields", typ)
+ f.Warn(c.Pos(), typeString+" composite literal uses untagged fields")
}
// pkgPath returns the import path "image/png" for the package name "png".
@@ -119,8 +139,6 @@ var untaggedLiteralWhitelist = map[string]bool{
"encoding/xml.CharData": true,
"encoding/xml.Comment": true,
"encoding/xml.Directive": true,
- "exp/norm.Decomposition": true,
- "exp/types.ObjList": true,
"go/scanner.ErrorList": true,
"image/color.Palette": true,
"net.HardwareAddr": true,
diff --git a/src/cmd/vet/test_asm.go b/src/cmd/vet/test_asm.go
new file mode 100644
index 000000000..098bdd15c
--- /dev/null
+++ b/src/cmd/vet/test_asm.go
@@ -0,0 +1,24 @@
+// Copyright 2010 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.
+
+// +build ignore
+
+// This file contains declarations to test the assembly in test_asm.s.
+
+package main
+
+func arg1(x int8, y uint8)
+func arg2(x int16, y uint16)
+func arg4(x int32, y uint32)
+func arg8(x int64, y uint64)
+func argint(x int, y uint)
+func argptr(x *byte, y *byte, c chan int, m map[int]int, f func())
+func argstring(x, y string)
+func argslice(x, y []string)
+func argiface(x interface{}, y interface {
+ m()
+})
+func returnint() int
+func returnbyte(x int) byte
+func returnnamed(x byte) (r1 int, r2 int16, r3 string, r4 byte)
diff --git a/src/cmd/vet/test_asm1.s b/src/cmd/vet/test_asm1.s
new file mode 100644
index 000000000..2fe31963a
--- /dev/null
+++ b/src/cmd/vet/test_asm1.s
@@ -0,0 +1,249 @@
+// Copyright 2013 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.
+
+// +build amd64
+// +build ignore
+
+package main
+
+TEXT ·arg1(SB),0,$0-2
+ MOVB x+0(FP), AX
+ MOVB y+1(FP), BX
+ MOVW x+0(FP), AX // ERROR "\[amd64\] invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+ MOVW y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int8 is 1-byte value"
+ MOVL y+1(FP), AX // ERROR "invalid MOVL of y\+1\(FP\); uint8 is 1-byte value"
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int8 is 1-byte value"
+ MOVQ y+1(FP), AX // ERROR "invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value"
+ MOVB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+ MOVB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+ TESTB x+0(FP), AX
+ TESTB y+1(FP), BX
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int8 is 1-byte value"
+ TESTW y+1(FP), AX // ERROR "invalid TESTW of y\+1\(FP\); uint8 is 1-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int8 is 1-byte value"
+ TESTL y+1(FP), AX // ERROR "invalid TESTL of y\+1\(FP\); uint8 is 1-byte value"
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int8 is 1-byte value"
+ TESTQ y+1(FP), AX // ERROR "invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value"
+ TESTB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+ TESTB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+ RET
+
+TEXT ·arg2(SB),0,$0-4
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+ MOVB y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+ MOVW x+0(FP), AX
+ MOVW y+2(FP), BX
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int16 is 2-byte value"
+ MOVL y+2(FP), AX // ERROR "invalid MOVL of y\+2\(FP\); uint16 is 2-byte value"
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int16 is 2-byte value"
+ MOVQ y+2(FP), AX // ERROR "invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value"
+ MOVW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+ MOVW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int16 is 2-byte value"
+ TESTB y+2(FP), AX // ERROR "invalid TESTB of y\+2\(FP\); uint16 is 2-byte value"
+ TESTW x+0(FP), AX
+ TESTW y+2(FP), BX
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int16 is 2-byte value"
+ TESTL y+2(FP), AX // ERROR "invalid TESTL of y\+2\(FP\); uint16 is 2-byte value"
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int16 is 2-byte value"
+ TESTQ y+2(FP), AX // ERROR "invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value"
+ TESTW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+ TESTW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+ RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int32 is 4-byte value"
+ MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint32 is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVL y+4(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int32 is 4-byte value"
+ MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value"
+ MOVL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int32 is 4-byte value"
+ TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint32 is 4-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int32 is 4-byte value"
+ TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint32 is 4-byte value"
+ TESTL x+0(FP), AX
+ TESTL y+4(FP), AX
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int32 is 4-byte value"
+ TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value"
+ TESTL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ TESTL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+ MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int64 is 8-byte value"
+ MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint64 is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVQ y+8(FP), AX
+ MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int64 is 8-byte value"
+ TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint64 is 8-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int64 is 8-byte value"
+ TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint64 is 8-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int64 is 8-byte value"
+ TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint64 is 8-byte value"
+ TESTQ x+0(FP), AX
+ TESTQ y+8(FP), AX
+ TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 8-byte value"
+ MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint is 8-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int is 8-byte value"
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int is 8-byte value"
+ MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVQ y+8(FP), AX
+ MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int is 8-byte value"
+ TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint is 8-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int is 8-byte value"
+ TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint is 8-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int is 8-byte value"
+ TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint is 8-byte value"
+ TESTQ x+0(FP), AX
+ TESTQ y+8(FP), AX
+ TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-40"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 8-byte value"
+ MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); \*byte is 8-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 8-byte value"
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); \*byte is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); \*byte is 8-byte value"
+ MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); \*byte is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVQ y+8(FP), AX
+ MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); \*byte is 8-byte value"
+ TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); \*byte is 8-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); \*byte is 8-byte value"
+ TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); \*byte is 8-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); \*byte is 8-byte value"
+ TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); \*byte is 8-byte value"
+ TESTQ x+0(FP), AX
+ TESTQ y+8(FP), AX
+ TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ MOVL c+16(FP), AX // ERROR "invalid MOVL of c\+16\(FP\); chan int is 8-byte value"
+ MOVL m+24(FP), AX // ERROR "invalid MOVL of m\+24\(FP\); map\[int\]int is 8-byte value"
+ MOVL f+32(FP), AX // ERROR "invalid MOVL of f\+32\(FP\); func\(\) is 8-byte value"
+ RET
+
+TEXT ·argstring(SB),0,$32 // ERROR "wrong argument size 0; expected \$\.\.\.-32"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); string base is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); string base is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 8-byte value"
+ MOVL x_base+0(FP), AX // ERROR "invalid MOVL of x_base\+0\(FP\); string base is 8-byte value"
+ MOVQ x_base+0(FP), AX
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVW x_len+8(FP), AX // ERROR "invalid MOVW of x_len\+8\(FP\); string len is 8-byte value"
+ MOVL x_len+8(FP), AX // ERROR "invalid MOVL of x_len\+8\(FP\); string len is 8-byte value"
+ MOVQ x_len+8(FP), AX
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+16\(FP\)"
+ MOVQ y_len+8(FP), AX // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)"
+ RET
+
+TEXT ·argslice(SB),0,$48 // ERROR "wrong argument size 0; expected \$\.\.\.-48"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); slice base is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); slice base is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value"
+ MOVL x_base+0(FP), AX // ERROR "invalid MOVL of x_base\+0\(FP\); slice base is 8-byte value"
+ MOVQ x_base+0(FP), AX
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVW x_len+8(FP), AX // ERROR "invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value"
+ MOVL x_len+8(FP), AX // ERROR "invalid MOVL of x_len\+8\(FP\); slice len is 8-byte value"
+ MOVQ x_len+8(FP), AX
+ MOVW x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+ MOVL x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+ MOVQ x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+ MOVW x_cap+16(FP), AX // ERROR "invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value"
+ MOVL x_cap+16(FP), AX // ERROR "invalid MOVL of x_cap\+16\(FP\); slice cap is 8-byte value"
+ MOVQ x_cap+16(FP), AX
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+24\(FP\)"
+ MOVQ y_len+8(FP), AX // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)"
+ MOVQ y_cap+16(FP), AX // ERROR "invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)"
+ RET
+
+TEXT ·argiface(SB),0,$0-32
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); interface type is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); interface type is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVW x_type+0(FP), AX // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value"
+ MOVL x_type+0(FP), AX // ERROR "invalid MOVL of x_type\+0\(FP\); interface type is 8-byte value"
+ MOVQ x_type+0(FP), AX
+ MOVQ x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+ MOVQ x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+ MOVW x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+ MOVL x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+ MOVQ x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+ MOVW x_data+8(FP), AX // ERROR "invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value"
+ MOVL x_data+8(FP), AX // ERROR "invalid MOVL of x_data\+8\(FP\); interface data is 8-byte value"
+ MOVQ x_data+8(FP), AX
+ MOVW y+16(FP), AX // ERROR "invalid MOVW of y\+16\(FP\); interface itable is 8-byte value"
+ MOVL y+16(FP), AX // ERROR "invalid MOVL of y\+16\(FP\); interface itable is 8-byte value"
+ MOVQ y+16(FP), AX
+ MOVW y_itable+16(FP), AX // ERROR "invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value"
+ MOVL y_itable+16(FP), AX // ERROR "invalid MOVL of y_itable\+16\(FP\); interface itable is 8-byte value"
+ MOVQ y_itable+16(FP), AX
+ MOVQ y_type+16(FP), AX // ERROR "unknown variable y_type; offset 16 is y_itable\+16\(FP\)"
+ MOVW y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+ MOVL y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+ MOVQ y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+ MOVW y_data+24(FP), AX // ERROR "invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value"
+ MOVL y_data+24(FP), AX // ERROR "invalid MOVL of y_data\+24\(FP\); interface data is 8-byte value"
+ MOVQ y_data+24(FP), AX
+ RET
+
+TEXT ·returnint(SB),0,$0-8
+ MOVB AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 8-byte value"
+ MOVW AX, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 8-byte value"
+ MOVL AX, ret+0(FP) // ERROR "invalid MOVL of ret\+0\(FP\); int is 8-byte value"
+ MOVQ AX, ret+0(FP)
+ MOVQ AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+ MOVQ AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+ RET
+
+TEXT ·returnbyte(SB),0,$0-9
+ MOVQ x+0(FP), AX
+ MOVB AX, ret+8(FP)
+ MOVW AX, ret+8(FP) // ERROR "invalid MOVW of ret\+8\(FP\); byte is 1-byte value"
+ MOVL AX, ret+8(FP) // ERROR "invalid MOVL of ret\+8\(FP\); byte is 1-byte value"
+ MOVQ AX, ret+8(FP) // ERROR "invalid MOVQ of ret\+8\(FP\); byte is 1-byte value"
+ MOVB AX, ret+7(FP) // ERROR "invalid offset ret\+7\(FP\); expected ret\+8\(FP\)"
+ RET
+
+TEXT ·returnnamed(SB),0,$0-41
+ MOVB x+0(FP), AX
+ MOVQ AX, r1+8(FP)
+ MOVW AX, r2+16(FP)
+ MOVQ AX, r3+24(FP)
+ MOVQ AX, r3_base+24(FP)
+ MOVQ AX, r3_len+32(FP)
+ MOVB AX, r4+40(FP)
+ MOVL AX, r1+8(FP) // ERROR "invalid MOVL of r1\+8\(FP\); int is 8-byte value"
+ RET
diff --git a/src/cmd/vet/test_asm2.s b/src/cmd/vet/test_asm2.s
new file mode 100644
index 000000000..73a4ad4be
--- /dev/null
+++ b/src/cmd/vet/test_asm2.s
@@ -0,0 +1,253 @@
+// Copyright 2013 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.
+
+// +build 386
+// +build ignore
+
+package main
+
+TEXT ·arg1(SB),0,$0-2
+ MOVB x+0(FP), AX
+ MOVB y+1(FP), BX
+ MOVW x+0(FP), AX // ERROR "\[386\] invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+ MOVW y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int8 is 1-byte value"
+ MOVL y+1(FP), AX // ERROR "invalid MOVL of y\+1\(FP\); uint8 is 1-byte value"
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int8 is 1-byte value"
+ MOVQ y+1(FP), AX // ERROR "invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value"
+ MOVB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+ MOVB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+ TESTB x+0(FP), AX
+ TESTB y+1(FP), BX
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int8 is 1-byte value"
+ TESTW y+1(FP), AX // ERROR "invalid TESTW of y\+1\(FP\); uint8 is 1-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int8 is 1-byte value"
+ TESTL y+1(FP), AX // ERROR "invalid TESTL of y\+1\(FP\); uint8 is 1-byte value"
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int8 is 1-byte value"
+ TESTQ y+1(FP), AX // ERROR "invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value"
+ TESTB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+ TESTB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+ RET
+
+TEXT ·arg2(SB),0,$0-4
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+ MOVB y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+ MOVW x+0(FP), AX
+ MOVW y+2(FP), BX
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int16 is 2-byte value"
+ MOVL y+2(FP), AX // ERROR "invalid MOVL of y\+2\(FP\); uint16 is 2-byte value"
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int16 is 2-byte value"
+ MOVQ y+2(FP), AX // ERROR "invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value"
+ MOVW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+ MOVW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int16 is 2-byte value"
+ TESTB y+2(FP), AX // ERROR "invalid TESTB of y\+2\(FP\); uint16 is 2-byte value"
+ TESTW x+0(FP), AX
+ TESTW y+2(FP), BX
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int16 is 2-byte value"
+ TESTL y+2(FP), AX // ERROR "invalid TESTL of y\+2\(FP\); uint16 is 2-byte value"
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int16 is 2-byte value"
+ TESTQ y+2(FP), AX // ERROR "invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value"
+ TESTW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+ TESTW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+ RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int32 is 4-byte value"
+ MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint32 is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVL y+4(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int32 is 4-byte value"
+ MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value"
+ MOVL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int32 is 4-byte value"
+ TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint32 is 4-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int32 is 4-byte value"
+ TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint32 is 4-byte value"
+ TESTL x+0(FP), AX
+ TESTL y+4(FP), AX
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int32 is 4-byte value"
+ TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value"
+ TESTL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ TESTL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+ MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+ MOVL x_lo+0(FP), AX
+ MOVL x_hi+4(FP), AX
+ MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+ MOVL y_lo+8(FP), AX
+ MOVL y_hi+12(FP), AX
+ MOVQ x+0(FP), AX
+ MOVQ y+8(FP), AX
+ MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int64 is 8-byte value"
+ TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint64 is 8-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int64 is 8-byte value"
+ TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint64 is 8-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+ TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+ TESTQ x+0(FP), AX
+ TESTQ y+8(FP), AX
+ TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint is 4-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int is 4-byte value"
+ MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVL y+4(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int is 4-byte value"
+ MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint is 4-byte value"
+ MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int is 4-byte value"
+ TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint is 4-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int is 4-byte value"
+ TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint is 4-byte value"
+ TESTL x+0(FP), AX
+ TESTL y+4(FP), AX
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int is 4-byte value"
+ TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint is 4-byte value"
+ TESTQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-20"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); \*byte is 4-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 4-byte value"
+ MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); \*byte is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVL y+4(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); \*byte is 4-byte value"
+ MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); \*byte is 4-byte value"
+ MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); \*byte is 4-byte value"
+ TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); \*byte is 4-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); \*byte is 4-byte value"
+ TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); \*byte is 4-byte value"
+ TESTL x+0(FP), AX
+ TESTL y+4(FP), AX
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); \*byte is 4-byte value"
+ TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); \*byte is 4-byte value"
+ TESTQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ MOVW c+8(FP), AX // ERROR "invalid MOVW of c\+8\(FP\); chan int is 4-byte value"
+ MOVW m+12(FP), AX // ERROR "invalid MOVW of m\+12\(FP\); map\[int\]int is 4-byte value"
+ MOVW f+16(FP), AX // ERROR "invalid MOVW of f\+16\(FP\); func\(\) is 4-byte value"
+ RET
+
+TEXT ·argstring(SB),0,$16 // ERROR "wrong argument size 0; expected \$\.\.\.-16"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); string base is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); string base is 4-byte value"
+ MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 4-byte value"
+ MOVL x_base+0(FP), AX
+ MOVQ x_base+0(FP), AX // ERROR "invalid MOVQ of x_base\+0\(FP\); string base is 4-byte value"
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVW x_len+4(FP), AX // ERROR "invalid MOVW of x_len\+4\(FP\); string len is 4-byte value"
+ MOVL x_len+4(FP), AX
+ MOVQ x_len+4(FP), AX // ERROR "invalid MOVQ of x_len\+4\(FP\); string len is 4-byte value"
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+8\(FP\)"
+ MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)"
+ RET
+
+TEXT ·argslice(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); slice base is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); slice base is 4-byte value"
+ MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 4-byte value"
+ MOVL x_base+0(FP), AX
+ MOVQ x_base+0(FP), AX // ERROR "invalid MOVQ of x_base\+0\(FP\); slice base is 4-byte value"
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVW x_len+4(FP), AX // ERROR "invalid MOVW of x_len\+4\(FP\); slice len is 4-byte value"
+ MOVL x_len+4(FP), AX
+ MOVQ x_len+4(FP), AX // ERROR "invalid MOVQ of x_len\+4\(FP\); slice len is 4-byte value"
+ MOVW x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVL x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVQ x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVW x_cap+8(FP), AX // ERROR "invalid MOVW of x_cap\+8\(FP\); slice cap is 4-byte value"
+ MOVL x_cap+8(FP), AX
+ MOVQ x_cap+8(FP), AX // ERROR "invalid MOVQ of x_cap\+8\(FP\); slice cap is 4-byte value"
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+12\(FP\)"
+ MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)"
+ MOVQ y_cap+8(FP), AX // ERROR "invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)"
+ RET
+
+TEXT ·argiface(SB),0,$0-16
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); interface type is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); interface type is 4-byte value"
+ MOVW x_type+0(FP), AX // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 4-byte value"
+ MOVL x_type+0(FP), AX
+ MOVQ x_type+0(FP), AX // ERROR "invalid MOVQ of x_type\+0\(FP\); interface type is 4-byte value"
+ MOVQ x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+ MOVQ x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+ MOVW x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVL x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVQ x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVW x_data+4(FP), AX // ERROR "invalid MOVW of x_data\+4\(FP\); interface data is 4-byte value"
+ MOVL x_data+4(FP), AX
+ MOVQ x_data+4(FP), AX // ERROR "invalid MOVQ of x_data\+4\(FP\); interface data is 4-byte value"
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); interface itable is 4-byte value"
+ MOVL y+8(FP), AX
+ MOVQ y+8(FP), AX // ERROR "invalid MOVQ of y\+8\(FP\); interface itable is 4-byte value"
+ MOVW y_itable+8(FP), AX // ERROR "invalid MOVW of y_itable\+8\(FP\); interface itable is 4-byte value"
+ MOVL y_itable+8(FP), AX
+ MOVQ y_itable+8(FP), AX // ERROR "invalid MOVQ of y_itable\+8\(FP\); interface itable is 4-byte value"
+ MOVQ y_type+8(FP), AX // ERROR "unknown variable y_type; offset 8 is y_itable\+8\(FP\)"
+ MOVW y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVL y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVQ y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVW y_data+12(FP), AX // ERROR "invalid MOVW of y_data\+12\(FP\); interface data is 4-byte value"
+ MOVL y_data+12(FP), AX
+ MOVQ y_data+12(FP), AX // ERROR "invalid MOVQ of y_data\+12\(FP\); interface data is 4-byte value"
+ RET
+
+TEXT ·returnint(SB),0,$0-4
+ MOVB AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 4-byte value"
+ MOVW AX, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 4-byte value"
+ MOVL AX, ret+0(FP)
+ MOVQ AX, ret+0(FP) // ERROR "invalid MOVQ of ret\+0\(FP\); int is 4-byte value"
+ MOVQ AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+ MOVQ AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+ RET
+
+TEXT ·returnbyte(SB),0,$0-5
+ MOVL x+0(FP), AX
+ MOVB AX, ret+4(FP)
+ MOVW AX, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
+ MOVL AX, ret+4(FP) // ERROR "invalid MOVL of ret\+4\(FP\); byte is 1-byte value"
+ MOVQ AX, ret+4(FP) // ERROR "invalid MOVQ of ret\+4\(FP\); byte is 1-byte value"
+ MOVB AX, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
+ RET
+
+TEXT ·returnnamed(SB),0,$0-21
+ MOVB x+0(FP), AX
+ MOVL AX, r1+4(FP)
+ MOVW AX, r2+8(FP)
+ MOVL AX, r3+12(FP)
+ MOVL AX, r3_base+12(FP)
+ MOVL AX, r3_len+16(FP)
+ MOVB AX, r4+20(FP)
+ MOVQ AX, r1+4(FP) // ERROR "invalid MOVQ of r1\+4\(FP\); int is 4-byte value"
+ RET
diff --git a/src/cmd/vet/test_asm3.s b/src/cmd/vet/test_asm3.s
new file mode 100644
index 000000000..2c1a54f3e
--- /dev/null
+++ b/src/cmd/vet/test_asm3.s
@@ -0,0 +1,168 @@
+// Copyright 2013 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.
+
+// +build arm
+// +build ignore
+
+package main
+
+TEXT ·arg1(SB),0,$0-2
+ MOVB x+0(FP), AX
+ MOVB y+1(FP), BX
+ MOVH x+0(FP), AX // ERROR "\[arm\] invalid MOVH of x\+0\(FP\); int8 is 1-byte value"
+ MOVH y+1(FP), AX // ERROR "invalid MOVH of y\+1\(FP\); uint8 is 1-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+ MOVW y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+ MOVB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+ MOVB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+ RET
+
+TEXT ·arg2(SB),0,$0-4
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+ MOVB y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+ MOVH x+0(FP), AX
+ MOVH y+2(FP), BX
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int16 is 2-byte value"
+ MOVW y+2(FP), AX // ERROR "invalid MOVW of y\+2\(FP\); uint16 is 2-byte value"
+ MOVH x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+ MOVH y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+ RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int32 is 4-byte value"
+ MOVH y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); uint32 is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVW y+4(FP), AX
+ MOVW x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVW y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+ MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int64 is 8-byte value"
+ MOVH y+8(FP), AX // ERROR "invalid MOVH of y\+8\(FP\); uint64 is 8-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+ MOVW x_lo+0(FP), AX
+ MOVW x_hi+4(FP), AX
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+ MOVW y_lo+8(FP), AX
+ MOVW y_hi+12(FP), AX
+ MOVQ x+0(FP), AX
+ MOVQ y+8(FP), AX
+ MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint is 4-byte value"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int is 4-byte value"
+ MOVH y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); uint is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVW y+4(FP), AX
+ MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-20"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); \*byte is 4-byte value"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); \*byte is 4-byte value"
+ MOVH y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); \*byte is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVW y+4(FP), AX
+ MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ MOVH c+8(FP), AX // ERROR "invalid MOVH of c\+8\(FP\); chan int is 4-byte value"
+ MOVH m+12(FP), AX // ERROR "invalid MOVH of m\+12\(FP\); map\[int\]int is 4-byte value"
+ MOVH f+16(FP), AX // ERROR "invalid MOVH of f\+16\(FP\); func\(\) is 4-byte value"
+ RET
+
+TEXT ·argstring(SB),0,$16 // ERROR "wrong argument size 0; expected \$\.\.\.-16"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); string base is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVH x_base+0(FP), AX // ERROR "invalid MOVH of x_base\+0\(FP\); string base is 4-byte value"
+ MOVW x_base+0(FP), AX
+ MOVH x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVH x_len+4(FP), AX // ERROR "invalid MOVH of x_len\+4\(FP\); string len is 4-byte value"
+ MOVW x_len+4(FP), AX
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+8\(FP\)"
+ MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)"
+ RET
+
+TEXT ·argslice(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); slice base is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVH x_base+0(FP), AX // ERROR "invalid MOVH of x_base\+0\(FP\); slice base is 4-byte value"
+ MOVW x_base+0(FP), AX
+ MOVH x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVH x_len+4(FP), AX // ERROR "invalid MOVH of x_len\+4\(FP\); slice len is 4-byte value"
+ MOVW x_len+4(FP), AX
+ MOVH x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVW x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVQ x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVH x_cap+8(FP), AX // ERROR "invalid MOVH of x_cap\+8\(FP\); slice cap is 4-byte value"
+ MOVW x_cap+8(FP), AX
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+12\(FP\)"
+ MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)"
+ MOVQ y_cap+8(FP), AX // ERROR "invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)"
+ RET
+
+TEXT ·argiface(SB),0,$0-16
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); interface type is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVH x_type+0(FP), AX // ERROR "invalid MOVH of x_type\+0\(FP\); interface type is 4-byte value"
+ MOVW x_type+0(FP), AX
+ MOVQ x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+ MOVQ x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+ MOVH x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVW x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVQ x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVH x_data+4(FP), AX // ERROR "invalid MOVH of x_data\+4\(FP\); interface data is 4-byte value"
+ MOVW x_data+4(FP), AX
+ MOVH y+8(FP), AX // ERROR "invalid MOVH of y\+8\(FP\); interface itable is 4-byte value"
+ MOVW y+8(FP), AX
+ MOVH y_itable+8(FP), AX // ERROR "invalid MOVH of y_itable\+8\(FP\); interface itable is 4-byte value"
+ MOVW y_itable+8(FP), AX
+ MOVQ y_type+8(FP), AX // ERROR "unknown variable y_type; offset 8 is y_itable\+8\(FP\)"
+ MOVH y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVW y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVQ y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVH y_data+12(FP), AX // ERROR "invalid MOVH of y_data\+12\(FP\); interface data is 4-byte value"
+ MOVW y_data+12(FP), AX
+ RET
+
+TEXT ·returnint(SB),0,$0-4
+ MOVB AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 4-byte value"
+ MOVH AX, ret+0(FP) // ERROR "invalid MOVH of ret\+0\(FP\); int is 4-byte value"
+ MOVW AX, ret+0(FP)
+ MOVQ AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+ MOVQ AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+ RET
+
+TEXT ·returnbyte(SB),0,$0-5
+ MOVW x+0(FP), AX
+ MOVB AX, ret+4(FP)
+ MOVH AX, ret+4(FP) // ERROR "invalid MOVH of ret\+4\(FP\); byte is 1-byte value"
+ MOVW AX, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
+ MOVB AX, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
+ RET
+
+TEXT ·returnnamed(SB),0,$0-21
+ MOVB x+0(FP), AX
+ MOVW AX, r1+4(FP)
+ MOVH AX, r2+8(FP)
+ MOVW AX, r3+12(FP)
+ MOVW AX, r3_base+12(FP)
+ MOVW AX, r3_len+16(FP)
+ MOVB AX, r4+20(FP)
+ MOVB AX, r1+4(FP) // ERROR "invalid MOVB of r1\+4\(FP\); int is 4-byte value"
+ RET
diff --git a/src/cmd/vet/test_assign.go b/src/cmd/vet/test_assign.go
new file mode 100644
index 000000000..8e0f45e53
--- /dev/null
+++ b/src/cmd/vet/test_assign.go
@@ -0,0 +1,20 @@
+// Copyright 2013 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.
+
+// This file contains tests for the useless-assignment checker.
+
+// +build vet_test
+
+package main
+
+type ST struct {
+ x int
+}
+
+func (s *ST) SetX(x int) {
+ // Accidental self-assignment; it should be "s.x = x"
+ x = x // ERROR "self-assignment of x to x"
+ // Another mistake
+ s.x = s.x // ERROR "self-assignment of s.x to s.x"
+}
diff --git a/src/cmd/vet/test_deadcode.go b/src/cmd/vet/test_deadcode.go
new file mode 100644
index 000000000..3ded80ca2
--- /dev/null
+++ b/src/cmd/vet/test_deadcode.go
@@ -0,0 +1,2121 @@
+// Copyright 2013 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.
+
+// +build vet_test
+// +build ignore
+
+// This file contains tests for the dead code checker.
+
+package main
+
+type T int
+
+var x interface{}
+var c chan int
+
+func external() int // ok
+
+func _() int {
+}
+
+func _() int {
+ print(1)
+}
+
+func _() int {
+ print(1)
+ return 2
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ print(1)
+ goto L
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ panic(2)
+ println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+func _() int {
+ var panic = func(int) {}
+ print(1)
+ panic(2)
+ println() // ok
+}
+
+func _() int {
+ {
+ print(1)
+ return 2
+ println() // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+ {
+ print(1)
+ return 2
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ println() // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+}
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ return 2
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ print(1)
+ goto L
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+ {
+ print(1)
+ return 2
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ {
+ print(1)
+ return 2
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ }
+ println() // ok
+}
+
+func _() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ for {
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ for {
+ for {
+ break
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ for {
+ for {
+ break
+ println() // ERROR "unreachable code"
+ }
+ }
+}
+
+func _() int {
+ for {
+ for {
+ continue
+ println() // ERROR "unreachable code"
+ }
+ }
+}
+
+func _() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ for {
+ break
+ }
+ println() // ok
+}
+
+func _() int {
+ for {
+ for {
+ }
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ for x == nil {
+ }
+ println() // ok
+}
+
+func _() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ for true {
+ }
+ println() // ok
+}
+
+func _() int {
+ for true {
+ for {
+ break
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ select {}
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for {
+ }
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for {
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ case c <- 1:
+ print(2)
+ goto L
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ default:
+ select {}
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select {}
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ }
+ println() // ok
+}
+
+func _() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L // ERROR "unreachable code"
+ case c <- 1:
+ print(2)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ select {
+ default:
+ break
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(1)
+ panic("abc")
+ default:
+ select {}
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ case 1:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch {
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L // ERROR "unreachable code"
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ break // ERROR "unreachable code"
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ case int:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch {
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ case float64:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L // ERROR "unreachable code"
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ break // ERROR "unreachable code"
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+func _() int {
+ println() // ok
+}
+
+func _() int {
+ return 2
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ goto L
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ panic(2)
+ println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+func _() int {
+ var panic = func(int) {}
+ panic(2)
+ println() // ok
+}
+
+func _() int {
+ {
+ return 2
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ {
+ return 2
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ {
+ goto L
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+L:
+ {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ {
+ panic(2)
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ {
+ panic(2)
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ return 2
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+func _() int {
+L:
+ goto L
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+func _() int {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+func _() int {
+ {
+ return 2
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+L:
+ {
+ goto L
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+ {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+ {
+ return 2
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+func _() int {
+L:
+ {
+ goto L
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+func _() int {
+ {
+ panic(2)
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+// again, with func literals
+
+var _ = func() int {
+}
+
+var _ = func() int {
+ print(1)
+}
+
+var _ = func() int {
+ print(1)
+ return 2
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ print(1)
+ goto L
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ panic(2)
+ println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+var _ = func() int {
+ var panic = func(int) {}
+ print(1)
+ panic(2)
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ println() // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ println() // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+}
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ return 2
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ print(1)
+ goto L
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ for {
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ for {
+ for {
+ break
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ for {
+ for {
+ break
+ println() // ERROR "unreachable code"
+ }
+ }
+}
+
+var _ = func() int {
+ for {
+ for {
+ continue
+ println() // ERROR "unreachable code"
+ }
+ }
+}
+
+var _ = func() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ for {
+ break
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ for {
+ for {
+ }
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ for x == nil {
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ for true {
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ for true {
+ for {
+ break
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ select {}
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for {
+ }
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for {
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ case c <- 1:
+ print(2)
+ goto L
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ default:
+ select {}
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select {}
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L // ERROR "unreachable code"
+ case c <- 1:
+ print(2)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ default:
+ break
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(1)
+ panic("abc")
+ default:
+ select {}
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ case 1:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch {
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L // ERROR "unreachable code"
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ break // ERROR "unreachable code"
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ case int:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch {
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ case float64:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L // ERROR "unreachable code"
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ break // ERROR "unreachable code"
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+var _ = func() int {
+ println() // ok
+}
+
+var _ = func() int {
+ return 2
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ goto L
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ panic(2)
+ println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+var _ = func() int {
+ var panic = func(int) {}
+ panic(2)
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ return 2
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ {
+ return 2
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ {
+ goto L
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+L:
+ {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ {
+ panic(2)
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ {
+ panic(2)
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ return 2
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ goto L
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+var _ = func() int {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ return 2
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ {
+ goto L
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ return 2
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ {
+ goto L
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ panic(2)
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
diff --git a/src/cmd/vet/test_taglit.go b/src/cmd/vet/test_taglit.go
index 0d83b18fd..f34062f18 100644
--- a/src/cmd/vet/test_taglit.go
+++ b/src/cmd/vet/test_taglit.go
@@ -15,6 +15,40 @@ import (
"go/scanner"
)
+var Okay1 = []string{
+ "Name",
+ "Usage",
+ "DefValue",
+}
+
+var Okay2 = map[string]bool{
+ "Name": true,
+ "Usage": true,
+ "DefValue": true,
+}
+
+var Okay3 = struct {
+ X string
+ Y string
+ Z string
+}{
+ "Name",
+ "Usage",
+ "DefValue",
+}
+
+type MyStruct struct {
+ X string
+ Y string
+ Z string
+}
+
+var Okay4 = MyStruct{
+ "Name",
+ "Usage",
+ "DefValue",
+}
+
// Testing is awkward because we need to reference things from a separate package
// to trigger the warnings.
diff --git a/src/cmd/vet/types.go b/src/cmd/vet/types.go
new file mode 100644
index 000000000..75f195b0f
--- /dev/null
+++ b/src/cmd/vet/types.go
@@ -0,0 +1,179 @@
+// Copyright 2010 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.
+
+// +build gotypes
+
+// This file contains the pieces of the tool that require the go/types package.
+// To compile this file, you must first run
+// $ go get code.google.com/p/go.exp/go/types
+
+package main
+
+import (
+ "go/ast"
+ "go/token"
+
+ "code.google.com/p/go.exp/go/types"
+)
+
+// Type is equivalent to go/types.Type. Repeating it here allows us to avoid
+// depending on the go/types package.
+type Type interface {
+ String() string
+}
+
+func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
+ pkg.types = make(map[ast.Expr]Type)
+ pkg.values = make(map[ast.Expr]interface{})
+ exprFn := func(x ast.Expr, typ types.Type, val interface{}) {
+ pkg.types[x] = typ
+ if val != nil {
+ pkg.values[x] = val
+ }
+ }
+ // By providing the Context with our own error function, it will continue
+ // past the first error. There is no need for that function to do anything.
+ context := types.Context{
+ Expr: exprFn,
+ Error: func(error) {},
+ }
+ _, err := context.Check(fs, astFiles)
+ return err
+}
+
+// isStruct reports whether the composite literal c is a struct.
+// If it is not (probably a struct), it returns a printable form of the type.
+func (pkg *Package) isStruct(c *ast.CompositeLit) (bool, string) {
+ // Check that the CompositeLit's type is a slice or array (which needs no tag), if possible.
+ typ := pkg.types[c]
+ // If it's a named type, pull out the underlying type.
+ actual := typ
+ if namedType, ok := typ.(*types.NamedType); ok {
+ actual = namedType.Underlying
+ }
+ if actual == nil {
+ // No type information available. Assume true, so we do the check.
+ return true, ""
+ }
+ switch actual.(type) {
+ case *types.Struct:
+ return true, typ.String()
+ default:
+ return false, ""
+ }
+}
+
+func (f *File) matchArgType(t printfArgType, arg ast.Expr) bool {
+ // TODO: for now, we can only test builtin types and untyped constants.
+ typ := f.pkg.types[arg]
+ if typ == nil {
+ return true
+ }
+ basic, ok := typ.(*types.Basic)
+ if !ok {
+ return true
+ }
+ switch basic.Kind {
+ case types.Bool:
+ return t&argBool != 0
+ case types.Int, types.Int8, types.Int16, types.Int32, types.Int64:
+ fallthrough
+ case types.Uint, types.Uint8, types.Uint16, types.Uint32, types.Uint64, types.Uintptr:
+ return t&argInt != 0
+ case types.Float32, types.Float64, types.Complex64, types.Complex128:
+ return t&argFloat != 0
+ case types.String:
+ return t&argString != 0
+ case types.UnsafePointer:
+ return t&(argPointer|argInt) != 0
+ case types.UntypedBool:
+ return t&argBool != 0
+ case types.UntypedComplex:
+ return t&argFloat != 0
+ case types.UntypedFloat:
+ // If it's integral, we can use an int format.
+ switch f.pkg.values[arg].(type) {
+ case int, int8, int16, int32, int64:
+ return t&(argInt|argFloat) != 0
+ case uint, uint8, uint16, uint32, uint64:
+ return t&(argInt|argFloat) != 0
+ }
+ return t&argFloat != 0
+ case types.UntypedInt:
+ return t&argInt != 0
+ case types.UntypedRune:
+ return t&(argInt|argRune) != 0
+ case types.UntypedString:
+ return t&argString != 0
+ case types.UntypedNil:
+ return t&argPointer != 0 // TODO?
+ case types.Invalid:
+ if *verbose {
+ f.Warnf(arg.Pos(), "printf argument %v has invalid or unknown type", arg)
+ }
+ return true // Probably a type check problem.
+ }
+ return false
+}
+
+// numArgsInSignature tells how many formal arguments the function type
+// being called has.
+func (f *File) numArgsInSignature(call *ast.CallExpr) int {
+ // Check the type of the function or method declaration
+ typ := f.pkg.types[call.Fun]
+ if typ == nil {
+ return 0
+ }
+ // The type must be a signature, but be sure for safety.
+ sig, ok := typ.(*types.Signature)
+ if !ok {
+ return 0
+ }
+ return len(sig.Params)
+}
+
+// isErrorMethodCall reports whether the call is of a method with signature
+// func Error() string
+// where "string" is the universe's string type. We know the method is called "Error".
+func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
+ // Is it a selector expression? Otherwise it's a function call, not a method call.
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return false
+ }
+ // The package is type-checked, so if there are no arguments, we're done.
+ if len(call.Args) > 0 {
+ return false
+ }
+ // Check the type of the method declaration
+ typ := f.pkg.types[sel]
+ if typ == nil {
+ return false
+ }
+ // The type must be a signature, but be sure for safety.
+ sig, ok := typ.(*types.Signature)
+ if !ok {
+ return false
+ }
+ // There must be a receiver for it to be a method call. Otherwise it is
+ // a function, not something that satisfies the error interface.
+ if sig.Recv == nil {
+ return false
+ }
+ // There must be no arguments. Already verified by type checking, but be thorough.
+ if len(sig.Params) > 0 {
+ return false
+ }
+ // Finally the real questions.
+ // There must be one result.
+ if len(sig.Results) != 1 {
+ return false
+ }
+ // It must have return type "string" from the universe.
+ result := sig.Results[0].Type
+ if types.IsIdentical(result, types.Typ[types.String]) {
+ return true
+ }
+ return false
+}
diff --git a/src/cmd/vet/typestub.go b/src/cmd/vet/typestub.go
new file mode 100644
index 000000000..fabbbe19d
--- /dev/null
+++ b/src/cmd/vet/typestub.go
@@ -0,0 +1,45 @@
+// Copyright 2010 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.
+
+// +build !gotypes
+
+// This file contains stubs for the pieces of the tool that require the go/types package,
+// to be used if go/types is not available.
+
+package main
+
+import (
+ "go/ast"
+ "go/token"
+)
+
+// Type is equivalent to go/types.Type. Repeating it here allows us to avoid
+// depending on the go/types package.
+type Type interface {
+ String() string
+}
+
+func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
+ return nil
+}
+
+func (pkg *Package) isStruct(c *ast.CompositeLit) (bool, string) {
+ return true, "" // Assume true, so we do the check.
+}
+
+func (f *File) matchArgType(t printfArgType, arg ast.Expr) bool {
+ return true // We can't tell without types.
+}
+
+func (f *File) numArgsInSignature(call *ast.CallExpr) int {
+ return 0 // We don't know.
+}
+
+func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
+ // Is it a selector expression? Otherwise it's a function call, not a method call.
+ if _, ok := call.Fun.(*ast.SelectorExpr); !ok {
+ return false
+ }
+ return true // Best guess we can make without types.
+}
diff --git a/src/cmd/yacc/yacc.go b/src/cmd/yacc/yacc.go
index 0c18f93b6..76b3aeac5 100644
--- a/src/cmd/yacc/yacc.go
+++ b/src/cmd/yacc/yacc.go
@@ -3164,7 +3164,6 @@ func ungetrune(f *bufio.Reader, c rune) {
func write(f *bufio.Writer, b []byte, n int) int {
panic("write")
- return 0
}
func open(s string) *bufio.Reader {