6g/6l: add go type information to symbol table.
  archive size +70%
  binary size +30%

old

wreck.mtv=; ls -l /Users/rsc/bin/{godoc,gofmt}
-rwxr-xr-x  1 rsc  eng  1487922 Aug 13 13:21 /Users/rsc/bin/godoc
-rwxr-xr-x  1 rsc  eng   995995 Aug 13 13:21 /Users/rsc/bin/gofmt
wreck.mtv=; du -sh $GOROOT/pkg/
9.5M	/home/rsc/go/pkg/
wreck.mtv=;

new

wreck.mtv=; ls -l /Users/rsc/bin/{godoc,gofmt}
-rwxr-xr-x  1 rsc  eng  2014390 Aug 13 14:25 /Users/rsc/bin/godoc
-rwxr-xr-x  1 rsc  eng  1268705 Aug 13 14:25 /Users/rsc/bin/gofmt
wreck.mtv=; du -sh $GOROOT/pkg
 16M	/home/rsc/go/pkg
wreck.mtv=;

R=ken
OCL=33217
CL=33220
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index 434a90a..c4c6e34 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -939,7 +939,8 @@
 		if(n->type != T) {
 			a->etype = simtype[n->type->etype];
 			a->width = n->type->width;
-		//	a->gotype = typename(n->type)->left->sym;
+			if(n->sym != S && strncmp(n->sym->name, "autotmp_", 8) != 0)
+				a->gotype = typename(n->type)->left->sym;
 		}
 		a->offset = n->xoffset;
 		a->sym = n->sym;
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index 3643eee..8f72812 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -106,6 +106,7 @@
 	Auto*	link;
 	int32	aoffset;
 	short	type;
+	Sym*	gotype;
 };
 struct	Sym
 {
@@ -123,6 +124,7 @@
 	Sym*	link;
 	Prog*	text;
 	Prog*	data;
+	Sym*	gotype;
 };
 struct	Optab
 {
@@ -403,7 +405,6 @@
 void	addstachmark(void);
 void	gethunk(void);
 void	gotypestrings(void);
-vlong	gotypefor(char*);
 void	histtoauto(void);
 double	ieeedtod(Ieee*);
 int32	ieeedtof(Ieee*);
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index f3c12d7..d9630fe3 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -614,14 +614,19 @@
 		return;
 
 	t = a->type;
-	if(t != D_AUTO && t != D_PARAM)
+	if(t != D_AUTO && t != D_PARAM) {
+		if(a->gotype)
+			s->gotype = a->gotype;
 		return;
+	}
 	l = a->offset;
 	for(u=curauto; u; u=u->link) {
 		if(u->asym == s)
 		if(u->type == t) {
 			if(u->aoffset > l)
 				u->aoffset = l;
+			if(a->gotype)
+				u->gotype = a->gotype;
 			return;
 		}
 	}
@@ -632,6 +637,7 @@
 	u->asym = s;
 	u->aoffset = l;
 	u->type = t;
+	u->gotype = a->gotype;
 }
 
 void
@@ -1062,7 +1068,7 @@
 		s = p->from.sym;
 		if(s != S && s->dupok) {
 			if(debug['v'])
-				Bprint(&bso, "skipping %s in %s: dupok", s->name, pn);
+				Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
 			goto loop;
 		}
 		if(s != S) {
@@ -1108,6 +1114,11 @@
 			}
 			diag("%s: redefinition: %s\n%P", pn, s->name, p);
 		}
+		if(p->from.gotype) {
+			if(s->gotype && s->gotype != p->from.gotype)
+				diag("%s: type mismatch for %s", pn, s->name);
+			s->gotype = p->from.gotype;
+		}
 		newtext(p, s);
 		goto loop;
 
diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c
index 4a36b0e..3fe8062 100644
--- a/src/cmd/6l/span.c
+++ b/src/cmd/6l/span.c
@@ -150,9 +150,10 @@
 }
 
 void
-putsymb(char *s, int t, vlong v, int ver, vlong go)
+putsymb(char *s, int t, vlong v, int ver, Sym *go)
 {
 	int i, f, l;
+	vlong gv;
 
 	if(t == 'f')
 		s++;
@@ -181,10 +182,13 @@
 			cput(s[i]);
 		cput(0);
 	}
+	gv = 0;
+	if(go)
+		gv = go->value+INITDAT;
 	if(l == 8)
-		lputb(go>>32);
-	lputb(go);
-	symsize += l + 1 + i + 1 + l;
+		lputb(gv>>32);
+	lputb(gv);
+	symsize += l + 1 + i+1 + l;
 
 	if(debug['n']) {
 		if(t == 'z' || t == 'Z') {
@@ -197,9 +201,9 @@
 			return;
 		}
 		if(ver)
-			Bprint(&bso, "%c %.8llux %s<%d> %s\n", t, v, s, ver, go);
+			Bprint(&bso, "%c %.8llux %s<%d> %s (%.8llux)\n", t, v, s, ver, go ? go->name : "", gv);
 		else
-			Bprint(&bso, "%c %.8llux %s %s\n", t, v, s, go);
+			Bprint(&bso, "%c %.8llux %s %s (%.8llux)\n", t, v, s, go ? go->name : "", gv);
 	}
 }
 
@@ -219,15 +223,15 @@
 		for(s=hash[h]; s!=S; s=s->link)
 			switch(s->type) {
 			case SCONST:
-				putsymb(s->name, 'D', s->value, s->version, gotypefor(s->name));
+				putsymb(s->name, 'D', s->value, s->version, s->gotype);
 				continue;
 
 			case SDATA:
-				putsymb(s->name, 'D', s->value+INITDAT, s->version, gotypefor(s->name));
+				putsymb(s->name, 'D', s->value+INITDAT, s->version, s->gotype);
 				continue;
 
 			case SBSS:
-				putsymb(s->name, 'B', s->value+INITDAT, s->version, gotypefor(s->name));
+				putsymb(s->name, 'B', s->value+INITDAT, s->version, s->gotype);
 				continue;
 
 			case SFILE:
@@ -248,7 +252,7 @@
 
 		if(s->type != STEXT)
 			continue;
-		putsymb(s->name, 'T', s->value, s->version, gotypefor(s->name));
+		putsymb(s->name, 'T', s->value, s->version, s->gotype);
 
 		/* frame, auto and param after */
 		putsymb(".frame", 'm', p->to.offset+8, 0, 0);
@@ -256,10 +260,10 @@
 		/* TODO(rsc): Add types for D_AUTO and D_PARAM */
 		for(a=p->to.autom; a; a=a->link)
 			if(a->type == D_AUTO)
-				putsymb(a->asym->name, 'a', -a->aoffset, 0, gotypefor(nil));
+				putsymb(a->asym->name, 'a', -a->aoffset, 0, a->gotype);
 			else
 			if(a->type == D_PARAM)
-				putsymb(a->asym->name, 'p', a->aoffset, 0, gotypefor(nil));
+				putsymb(a->asym->name, 'p', a->aoffset, 0, a->gotype);
 	}
 	if(debug['v'] || debug['n'])
 		Bprint(&bso, "symsize = %lud\n", symsize);
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index baf484e..922de00 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -119,6 +119,7 @@
 	Sym*	link;
 	Prog*	text;
 	Prog*	data;
+	Sym*	gotype;
 };
 struct	Optab
 {
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index ef7cd3e..199f536 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -442,7 +442,10 @@
 Node*
 typenod(Type *t)
 {
-	if(t->nod == N) {
+	// if we copied another type with *t = *u
+	// then t->nod might be out of date, so
+	// check t->nod->type too
+	if(t->nod == N || t->nod->type != t) {
 		t->nod = nod(OTYPE, N, N);
 		t->nod->type = t;
 		t->nod->sym = t->sym;
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index 6d2154b..49216b9 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -51,6 +51,8 @@
 			fatal("external %#N nil type\n", n);
 		if(n->class == PFUNC)
 			continue;
+		if(n->sym->package != package)
+			continue;
 		dowidth(n->type);
 
 		// TODO(rsc): why is this not s/n->sym->def/n/ ?
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index 9a1ad08..597b6a6 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -450,6 +450,8 @@
 	Sym *s;
 	Node *n;
 
+	if(isptr[t->etype] && t->type == T)
+		fatal("typename %T", t);
 	s = typesym(t);
 	if(s->def == N) {
 		n = nod(ONAME, N, N);
@@ -496,6 +498,8 @@
 			goto ok;
 		if(t1 && t1 == types[t1->etype])
 			goto ok;
+		if(t1 && t1->etype == tptr && t1->type->etype == TANY)
+			goto ok;
 	}
 
 	// named types from other files are defined in those files
@@ -666,13 +670,13 @@
 			dtypesym(ptrto(t));
 	}
 
-	// do basic types if compiling package runtime, type.go.
+	// do basic types if compiling package runtime.
 	// they have to be in at least one package,
 	// and reflect is always loaded implicitly,
 	// so this is as good as any.
 	// another possible choice would be package main,
 	// but using runtime means fewer copies in .6 files.
-	if(strcmp(package, "runtime") == 0 && strcmp(filename, "type") == 0) {
+	if(strcmp(package, "runtime") == 0) {
 		for(i=1; i<=TBOOL; i++)
 			if(i != TFLOAT80)
 				dtypesym(ptrto(types[i]));
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index fef39c8..891dee2 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -366,6 +366,8 @@
 		marktext(s->text);
 	if(s->data)
 		markdata(s->data, s);
+	if(s->gotype)
+		mark(s->gotype);
 }
 
 static void