]> Cypherpunks repositories - gostls13.git/commitdiff
* move go-specific loader code
authorRuss Cox <rsc@golang.org>
Tue, 31 Mar 2009 07:20:07 +0000 (00:20 -0700)
committerRuss Cox <rsc@golang.org>
Tue, 31 Mar 2009 07:20:07 +0000 (00:20 -0700)
into gc directory, where it gets included as ../gc/ldbody
this is similar to the assemblers including ../cc/lexbody
and ../cc/macbody.

* hook go-specific loader code into 8l.

* make current 8.out.h and 6.out.h backward compatible
with plan 9's versions.  i had added some constants in
the middle of enums and have now moved them to the end.
this keeps us from invalidating old .8 and .6 files.
not sure how much it really matters, but easy to do.

R=r
DELTA=1314  (667 added, 623 deleted, 24 changed)
OCL=26938
CL=26941

13 files changed:
src/cmd/6l/6.out.h
src/cmd/6l/Makefile
src/cmd/6l/go.c
src/cmd/6l/l.h
src/cmd/8l/8.out.h
src/cmd/8l/Makefile
src/cmd/8l/l.h
src/cmd/8l/list.c
src/cmd/8l/obj.c
src/cmd/8l/optab.c
src/cmd/8l/pass.c
src/cmd/8l/span.c
src/cmd/ld/go.c [new file with mode: 0644]

index 0c22944fa933891011e872e32c40e3edd8804807..15815f4e0d83eee21d534dbc38c1a7ae183299ef 100644 (file)
@@ -820,10 +820,10 @@ enum
        D_FILE,
        D_FILE1,
 
-       D_SBIG, /* internal use by 6l only */
-
        D_INDIR,        /* additive */
 
+       D_SBIG = D_INDIR + D_INDIR,
+
        T_TYPE          = 1<<0,
        T_INDEX         = 1<<1,
        T_OFFSET        = 1<<2,
index 5db1ba8bd2030cc0fe947918f674d7408a9ae1a2..eba976c638566687a7f75b41e0bc24bde7a4ccd7 100644 (file)
@@ -36,3 +36,5 @@ clean:
 
 install: $(TARG)
        cp $(TARG) $(BIN)/$(TARG)
+
+go.o: ../ld/go.c
index 961a3320b0ef857117243437152dc2d7044663ef..82a216520fcc96eee989fff096cf7659ab32dd49 100644 (file)
@@ -2,603 +2,5 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// go-specific
-
-// accumulate all type information from .6 files.
-// check for inconsistencies.
-// define gotypestrings variable if needed.
-// define gotypesigs variable if needed.
-
-// TODO:
-//     include type info for non-exported types.
-//     generate debugging section in binary.
-//     once the dust settles, try to move some code to
-//             libmach, so that other linkers and ar can share.
-//     try to make this completely portable and shared
-//             across linkers
-
 #include "l.h"
-
-/*
- *     package import data
- */
-typedef struct Import Import;
-struct Import
-{
-       Import *hash;   // next in hash table
-       int export;     // marked as export?
-       char *prefix;   // "type", "var", "func", "const"
-       char *name;
-       char *def;
-       char *file;
-};
-enum {
-       NIHASH = 1024
-};
-static Import *ihash[NIHASH];
-static int nimport;
-
-static int
-hashstr(char *name)
-{
-       int h;
-       char *cp;
-
-       h = 0;
-       for(cp = name; *cp; h += *cp++)
-               h *= 1119;
-       if(h < 0)
-               h = ~h;
-       return h;
-}
-
-static Import *
-ilookup(char *name)
-{
-       int h;
-       Import *x;
-
-       h = hashstr(name) % NIHASH;
-       for(x=ihash[h]; x; x=x->hash)
-               if(x->name[0] == name[0] && strcmp(x->name, name) == 0)
-                       return x;
-       x = mal(sizeof *x);
-       x->name = name;
-       x->hash = ihash[h];
-       ihash[h] = x;
-       nimport++;
-       return x;
-}
-
-char*
-gotypefor(char *name)
-{
-       Import *x;
-       char *s, *p;
-
-       s = strdup(name);
-       p = utfrune(s, 0xB7);   // center dot
-       if(p == nil)
-               return nil;
-       *p++ = '.';
-       memmove(p, p+1, strlen(p));
-       x = ilookup(s);
-       free(s);
-       if(x == nil || x->prefix == nil)
-               return nil;
-       if(strcmp(x->prefix, "var") != 0 && strcmp(x->prefix, "func") != 0)
-               return nil;
-       return x->def;
-}
-
-static void loadpkgdata(char*, char*, int);
-static int parsemethod(char**, char*, char**);
-static int parsepkgdata(char*, char**, char*, int*, char**, char**, char**);
-
-void
-ldpkg(Biobuf *f, int64 len, char *filename)
-{
-       char *data, *p0, *p1;
-
-       if(debug['g'])
-               return;
-
-       if((int)len != len) {
-               fprint(2, "6l: too much pkg data in %s\n", filename);
-               return;
-       }
-       data = mal(len);
-       if(Bread(f, data, len) != len) {
-               fprint(2, "6l: short pkg read %s\n", filename);
-               return;
-       }
-
-       // first \n$$ marks beginning of exports - skip rest of line
-       p0 = strstr(data, "\n$$");
-       if(p0 == nil)
-               return;
-       p0 += 3;
-       while(*p0 != '\n' && *p0 != '\0')
-               p0++;
-
-       // second marks end of exports / beginning of local data
-       p1 = strstr(p0, "\n$$");
-       if(p1 == nil) {
-               fprint(2, "6l: cannot find end of exports in %s\n", filename);
-               return;
-       }
-       while(*p0 == ' ' || *p0 == '\t' || *p0 == '\n')
-               p0++;
-       if(strncmp(p0, "package ", 8) != 0) {
-               fprint(2, "6l: bad package section in %s\n", filename);
-               return;
-       }
-       p0 += 8;
-       while(*p0 == ' ' || *p0 == '\t' || *p0 == '\n')
-               p0++;
-       while(*p0 != ' ' && *p0 != '\t' && *p0 != '\n')
-               p0++;
-
-       loadpkgdata(filename, p0, p1 - p0);
-
-       // local types begin where exports end.
-       // skip rest of line after $$ we found above
-       p0 = p1 + 3;
-       while(*p0 != '\n' && *p0 != '\0')
-               p0++;
-
-       // local types end at next \n$$.
-       p1 = strstr(p0, "\n$$");
-       if(p1 == nil) {
-               fprint(2, "6l: cannot find end of local types in %s\n", filename);
-               return;
-       }
-
-       loadpkgdata(filename, p0, p1 - p0);
-}
-
-static void
-loadpkgdata(char *file, char *data, int len)
-{
-       int export;
-       char *p, *ep, *prefix, *name, *def;
-       Import *x;
-
-       file = strdup(file);
-       p = data;
-       ep = data + len;
-       while(parsepkgdata(file, &p, ep, &export, &prefix, &name, &def) > 0) {
-               x = ilookup(name);
-               if(x->prefix == nil) {
-                       x->prefix = prefix;
-                       x->def = def;
-                       x->file = file;
-                       x->export = export;
-               } else {
-                       if(strcmp(x->prefix, prefix) != 0) {
-                               fprint(2, "6l: conflicting definitions for %s\n", name);
-                               fprint(2, "%s:\t%s %s ...\n", x->file, x->prefix, name);
-                               fprint(2, "%s:\t%s %s ...\n", file, prefix, name);
-                               nerrors++;
-                       }
-                       else if(strcmp(x->def, def) != 0) {
-                               fprint(2, "6l: conflicting definitions for %s\n", name);
-                               fprint(2, "%s:\t%s %s %s\n", x->file, x->prefix, name, x->def);
-                               fprint(2, "%s:\t%s %s %s\n", file, prefix, name, def);
-                               nerrors++;
-                       }
-
-                       // okay if some .6 say export and others don't.
-                       // all it takes is one.
-                       if(export)
-                               x->export = 1;
-               }
-       }
-}
-
-static int
-parsepkgdata(char *file, char **pp, char *ep, int *exportp, char **prefixp, char **namep, char **defp)
-{
-       char *p, *prefix, *name, *def, *edef, *meth;
-       int n;
-
-       // skip white space
-       p = *pp;
-       while(p < ep && (*p == ' ' || *p == '\t' || *p == '\n'))
-               p++;
-       if(p == ep || strncmp(p, "$$\n", 3) == 0)
-               return 0;
-
-       // [export|package ]
-       *exportp = 0;
-       if(p + 7 <= ep && strncmp(p, "export ", 7) == 0) {
-               *exportp = 1;
-               p += 7;
-       }
-       else if(p + 8 <= ep && strncmp(p, "package ", 8) == 0) {
-               *exportp = 2;
-               p += 8;
-       }
-
-       // prefix: (var|type|func|const)
-       prefix = p;
-
-       prefix = p;
-       if(p + 6 > ep)
-               return -1;
-       if(strncmp(p, "var ", 4) == 0)
-               p += 4;
-       else if(strncmp(p, "type ", 5) == 0)
-               p += 5;
-       else if(strncmp(p, "func ", 5) == 0)
-               p += 5;
-       else if(strncmp(p, "const ", 6) == 0)
-               p += 6;
-       else{
-               fprint(2, "6l: confused in pkg data near <<%.20s>>\n", p);
-               nerrors++;
-               return -1;
-       }
-       p[-1] = '\0';
-
-       // name: a.b followed by space
-       name = p;
-       while(p < ep && *p != ' ')
-               p++;
-       if(p >= ep)
-               return -1;
-       *p++ = '\0';
-
-       // def: free form to new line
-       def = p;
-       while(p < ep && *p != '\n')
-               p++;
-       if(p >= ep)
-               return -1;
-       edef = p;
-       *p++ = '\0';
-
-       // include methods on successive lines in def of named type
-       while(parsemethod(&p, ep, &meth) > 0) {
-               *edef++ = '\n'; // overwrites '\0'
-               if(edef+1 > meth) {
-                       // We want to indent methods with a single \t.
-                       // 6g puts at least one char of indent before all method defs,
-                       // so there will be room for the \t.  If the method def wasn't
-                       // indented we could do something more complicated,
-                       // but for now just diagnose the problem and assume
-                       // 6g will keep indenting for us.
-                       fprint(2, "6l: %s: expected methods to be indented %p %p %.10s\n",
-                               file, edef, meth, meth);
-                       nerrors++;
-                       return -1;
-               }
-               *edef++ = '\t';
-               n = strlen(meth);
-               memmove(edef, meth, n);
-               edef += n;
-       }
-
-       // done
-       *pp = p;
-       *prefixp = prefix;
-       *namep = name;
-       *defp = def;
-       return 1;
-}
-
-static int
-parsemethod(char **pp, char *ep, char **methp)
-{
-       char *p;
-
-       // skip white space
-       p = *pp;
-       while(p < ep && (*p == ' ' || *p == '\t'))
-               p++;
-       if(p == ep)
-               return 0;
-
-       // if it says "func (", it's a method
-       if(p + 6 >= ep || strncmp(p, "func (", 6) != 0)
-               return 0;
-
-       // definition to end of line
-       *methp = p;
-       while(p < ep && *p != '\n')
-               p++;
-       if(p >= ep) {
-               fprint(2, "6l: lost end of line in method definition\n");
-               *pp = ep;
-               return -1;
-       }
-       *p++ = '\0';
-       *pp = p;
-       return 1;
-}
-
-static int
-importcmp(const void *va, const void *vb)
-{
-       Import *a, *b;
-
-       a = *(Import**)va;
-       b = *(Import**)vb;
-       return strcmp(a->name, b->name);
-}
-
-static int
-symcmp(const void *va, const void *vb)
-{
-       Sym *a, *b;
-
-       a = *(Sym**)va;
-       b = *(Sym**)vb;
-       return strcmp(a->name, b->name);
-}
-
-// if there is an undefined reference to gotypestrings,
-// create it.  c declaration is
-//     extern char gotypestrings[];
-// ironically, gotypestrings is a c variable, because there
-// is no way to forward declare a string in go.
-void
-definetypestrings(void)
-{
-       int i, j, len, n, w;
-       char *p;
-       Import **all, *x;
-       Fmt f;
-       Prog *prog;
-       Sym *s;
-
-       if(debug['g'])
-               return;
-
-       if(debug['v'])
-               Bprint(&bso, "%5.2f definetypestrings\n", cputime());
-
-       s = lookup("gotypestrings", 0);
-       if(s->type == 0)
-               return;
-       if(s->type != SXREF) {
-               diag("gotypestrings already defined");
-               return;
-       }
-       s->type = SDATA;
-
-       // make a list of all the type exports
-       n = 0;
-       for(i=0; i<NIHASH; i++)
-               for(x=ihash[i]; x; x=x->hash)
-                       if(strcmp(x->prefix, "type") == 0)
-                               n++;
-       all = mal(n*sizeof all[0]);
-       j = 0;
-       for(i=0; i<NIHASH; i++)
-               for(x=ihash[i]; x; x=x->hash)
-                       if(strcmp(x->prefix, "type") == 0)
-                               all[j++] = x;
-
-       // sort them by name
-       qsort(all, n, sizeof all[0], importcmp);
-
-       // make a big go string containing all the types
-       fmtstrinit(&f);
-       fmtprint(&f, "xxxx");   // 4-byte length
-       for(i=0; i<n; i++) {
-               p = strchr(all[i]->def, '\n');
-               if(p)
-                       len = p - all[i]->def;
-               else
-                       len = strlen(all[i]->def);
-               fmtprint(&f, "%s %.*s\n", all[i]->name, utfnlen(all[i]->def, len), all[i]->def);
-       }
-       p = fmtstrflush(&f);
-       n = strlen(p);
-       s->value = n;
-
-       // go strings begin with 4-byte length.
-       // amd64 is little-endian.
-       len = n - 4;
-       p[0] = len;
-       p[1] = len >> 8;
-       p[2] = len >> 16;
-       p[3] = len >> 24;
-
-       // have data, need to create linker representation.
-       // linker stores big data as sequence of pieces
-       // with int8 length, so break p into 100-byte chunks.
-       // (had to add D_SBIG even to do that; the compiler
-       // would have generated 8-byte chunks.)
-       for(i=0; i<n; i+=100) {
-               w = 100;
-               if(w > n - i)
-                       w = n - i;
-               prog = newdata(s, i, w, D_EXTERN);
-               prog->to.type = D_SBIG;
-               prog->to.sbig = p + i;
-       }
-
-       if(debug['v'])
-               Bprint(&bso, "%5.2f typestrings %d\n", cputime(), n);
-}
-
-// if there is an undefined reference to gotypesigs, create it.
-// c declaration is
-//     extern Sigt *gotypesigs[];
-//     extern int ngotypesigs;
-// used by sys.unreflect runtime.
-void
-definetypesigs(void)
-{
-       int i, j, n;
-       Sym **all, *s, *x;
-       Prog *prog;
-
-       if(debug['g'])
-               return;
-
-       if(debug['v'])
-               Bprint(&bso, "%5.2f definetypesigs\n", cputime());
-
-       s = lookup("gotypesigs", 0);
-       if(s->type == 0)
-               return;
-       if(s->type != SXREF) {
-               diag("gotypesigs already defined");
-               return;
-       }
-       s->type = SDATA;
-
-       // make a list of all the sigt symbols.
-       n = 0;
-       for(i=0; i<NHASH; i++)
-               for(x = hash[i]; x; x=x->link)
-                       if(memcmp(x->name, "sigt·", 6) == 0 && x->type != Sxxx)
-                               n++;
-       all = mal(n*sizeof all[0]);
-       j = 0;
-       for(i=0; i<NHASH; i++)
-               for(x = hash[i]; x; x=x->link)
-                       if(memcmp(x->name, "sigt·", 6) == 0 && x->type != Sxxx)
-                               all[j++] = x;
-
-       // sort them by name
-       qsort(all, n, sizeof all[0], symcmp);
-
-       // emit array as sequence of references.
-       enum { PtrSize = 8 };
-       for(i=0; i<n; i++) {
-               prog = newdata(s, PtrSize*i, PtrSize, D_EXTERN);
-               prog->to.type = D_ADDR;
-               prog->to.index = D_EXTERN;
-               prog->to.sym = all[i];
-       }
-       s->value = PtrSize*n;
-       if(n == 0)
-               s->value = 1;   // must have non-zero size or 6l complains
-
-       // emit count
-       s = lookup("ngotypesigs", 0);
-       s->type = SDATA;
-       s->value = sizeof(int32);
-       prog = newdata(s, 0, sizeof(int32), D_EXTERN);
-       prog->to.offset = n;
-
-       if(debug['v'])
-               Bprint(&bso, "%5.2f typesigs %d\n", cputime(), n);
-}
-
-int
-isinitfunc(Sym *s)
-{
-       char *p;
-
-       p = utfrune(s->name, 0xb7);     // 0xb7 = '·'
-       if(p == nil)
-               return 0;
-       if(memcmp(p, "·Init·", 8) == 0 || memcmp(p, "·init·", 8) == 0)
-               return 1;
-       return 0;
-}
-
-static void mark(Sym*);
-static int markdepth;
-
-static void
-markdata(Prog *p, Sym *s)
-{
-       markdepth++;
-       if(p != P && debug['v'] > 1)
-               Bprint(&bso, "%d markdata %s\n", markdepth, s->name);
-       for(; p != P; p=p->dlink)
-               if(p->to.sym)
-                       mark(p->to.sym);
-       markdepth--;
-}
-
-static void
-marktext(Prog *p)
-{
-       if(p == P)
-               return;
-       if(p->as != ATEXT) {
-               diag("marktext: %P", p);
-               return;
-       }
-       markdepth++;
-       if(debug['v'] > 1)
-               Bprint(&bso, "%d marktext %s\n", markdepth, p->from.sym->name);
-       for(p=p->link; p != P; p=p->link) {
-               if(p->as == ATEXT || p->as == ADATA || p->as == AGLOBL)
-                       break;
-               if(p->from.sym)
-                       mark(p->from.sym);
-               if(p->to.sym)
-                       mark(p->to.sym);
-       }
-       markdepth--;
-}
-
-static void
-mark(Sym *s)
-{
-       if(s == S || s->reachable)
-               return;
-       s->reachable = 1;
-       if(s->text)
-               marktext(s->text);
-       if(s->data)
-               markdata(s->data, s);
-}
-
-static void
-sweeplist(Prog **first, Prog **last)
-{
-       int reachable;
-       Prog *p, *q;
-
-       reachable = 1;
-       q = P;
-       for(p=*first; p != P; p=p->link) {
-               switch(p->as) {
-               case ATEXT:
-               case ADATA:
-               case AGLOBL:
-                       reachable = p->from.sym->reachable;
-                       if(!reachable) {
-                               if(debug['v'] > 1)
-                                       Bprint(&bso, "discard %s\n", p->from.sym->name);
-                               p->from.sym->type = Sxxx;
-                       }
-                       break;
-               }
-               if(reachable) {
-                       if(q == P)
-                               *first = p;
-                       else
-                               q->link = p;
-                       q = p;
-               }
-       }
-       if(q == P)
-               *first = P;
-       else
-               q->link = P;
-       *last = q;
-}
-
-void
-deadcode(void)
-{
-       if(debug['v'])
-               Bprint(&bso, "%5.2f deadcode\n", cputime());
-
-       mark(lookup(INITENTRY, 0));
-       mark(lookup("sys·morestack", 0));
-
-       sweeplist(&firstp, &lastp);
-       sweeplist(&datap, &edatap);
-}
-
+#include "../ld/go.c"
index 83c28bd4b7bf9c7ea8e26c4f42258db291d72230..2d3cd535a111c95e767dfcefdcd3b1620f1aa6eb 100644 (file)
@@ -441,7 +441,6 @@ void        xdefine(char*, int, vlong);
 void   xfol(Prog*);
 void   zaddr(Biobuf*, Adr*, Sym*[]);
 void   zerosig(char*);
-int    isinitfunc(Sym*);
 
 void   machseg(char*, vlong, vlong, vlong, vlong, uint32, uint32, uint32, uint32);
 void   machsymseg(uint32, uint32);
index f7750129d8e6617eb333569ea76481d705f28591..1b9c88b1d99c85b7d71841751b62a47c9f3f4af9 100644 (file)
@@ -79,9 +79,6 @@ enum  as
        ACMPSB,
        ACMPSL,
        ACMPSW,
-       ACMPXCHGB,
-       ACMPXCHGL,
-       ACMPXCHGW,
        ADAA,
        ADAS,
        ADATA,
@@ -387,6 +384,10 @@ enum       as
 
        ASIGNAME,
 
+       ACMPXCHGB,
+       ACMPXCHGL,
+       ACMPXCHGW,
+
        ALAST
 };
 
@@ -441,13 +442,15 @@ enum
        D_FCONST        = 66,
        D_SCONST        = 67,
        D_ADDR          = 68,
-       D_CONST2        = 69,
 
        D_FILE,
        D_FILE1,
 
        D_INDIR,        /* additive */
 
+       D_SBIG = D_INDIR + D_INDIR,
+       D_CONST2,
+
        T_TYPE          = 1<<0,
        T_INDEX         = 1<<1,
        T_OFFSET        = 1<<2,
index e11b6687a97ae8517620a9f3c277562b94ed2f9a..6b8c73ae2e57d064072a7ebf4b491921a5319bef 100644 (file)
@@ -16,6 +16,7 @@ OFILES=\
        optab.$O\
        pass.$O\
        span.$O\
+       go.$O\
 
 HFILES=\
        l.h\
@@ -35,3 +36,6 @@ clean:
 
 install: $(TARG)
        cp $(TARG) $(BIN)/$(TARG)
+
+go.o: ../ld/go.c
+
index 114c66369042beeb3bfa56348061909d931376d2..9afd78faa2a19e8bf981e8b24b915e7ede6826c8 100644 (file)
@@ -58,6 +58,7 @@ struct        Adr
                char    u0scon[8];
                Prog    *u0cond;        /* not used, but should be D_BRANCH */
                Ieee    u0ieee;
+               char    *u0sbig;
        } u0;
        union
        {
@@ -74,6 +75,7 @@ struct        Adr
 #define        scon    u0.u0scon
 #define        cond    u0.u0cond
 #define        ieee    u0.u0ieee
+#define        sbig    u0.u0sbig
 
 #define        autom   u1.u1autom
 #define        sym     u1.u1sym
@@ -84,6 +86,7 @@ struct        Prog
        Adr     to;
        Prog    *forwd;
        Prog*   link;
+       Prog*   dlink;
        Prog*   pcond;  /* work on this */
        int32   pc;
        int32   line;
@@ -108,10 +111,14 @@ struct    Sym
        short   become;
        short   frame;
        uchar   subtype;
+       uchar   dupok;
+       uchar   reachable;
        ushort  file;
        int32   value;
        int32   sig;
        Sym*    link;
+       Prog*   text;
+       Prog*   data;
 };
 struct Optab
 {
@@ -123,7 +130,9 @@ struct      Optab
 
 enum
 {
-       STEXT           = 1,
+       Sxxx,
+
+       STEXT,
        SDATA,
        SBSS,
        SDATA1,
@@ -352,6 +361,8 @@ void        lputl(int32);
 void   main(int, char*[]);
 void   mkfwd(void);
 void*  mal(uint32);
+Prog*  newdata(Sym*, int, int, int);
+Prog*  newtext(Prog*, Sym*);
 void   nuxiinit(void);
 void   objfile(char*);
 int    opsize(Prog*);
@@ -375,6 +386,16 @@ uint32     machheadr(void);
 uint32 elfheadr(void);
 void   whatsys(void);
 
+/*
+ *     go.c
+ */
+void   deadcode(void);
+void   definetypestrings(void);
+void   definetypesigs(void);
+char*  gotypefor(char *name);
+void   ldpkg(Biobuf *f, int64 len, char *filename);
+
+
 /* set by call to whatsys() */
 extern char*   goroot;
 extern char*   goarch;
index 873f7c1f857b16544f5ea6fade37c7a48f3579db..79777d8b1f300dcac4fc7ab5490f5e94be539d4f 100644 (file)
@@ -99,7 +99,7 @@ Dconv(Fmt *fp)
 
        a = va_arg(fp->args, Adr*);
        i = a->type;
-       if(i >= D_INDIR) {
+       if(i >= D_INDIR && i < 2*D_INDIR) {
                if(a->offset)
                        sprint(str, "%ld(%R)", a->offset, i-D_INDIR);
                else
index c4aa3486be157385a8c16f772f43713d56974f20..a14f52d6f7256f72b620811d7d77f04f121f2319 100644 (file)
@@ -333,6 +333,10 @@ main(int argc, char *argv[])
                sprint(a, "%s/lib/lib_%s_%s.a", goroot, goarch, goos);
                objfile(a);
        }
+       definetypestrings();
+       definetypesigs();
+       deadcode();
+
        firstp = firstp->link;
        if(firstp == P)
                errorexit();
@@ -848,7 +852,7 @@ ldobj(Biobuf *f, int32 len, char *pn)
        import1 = Boffset(f);
 
        Bseek(f, import0, 0);
-//     ldpkg(f, import1 - import0 - 2, pn);    // -2 for !\n
+       ldpkg(f, import1 - import0 - 2, pn);    // -2 for !\n
        Bseek(f, import1, 0);
 
 newloop:
@@ -1017,6 +1021,20 @@ loop:
 
        case ADATA:
        data:
+               // Assume that AGLOBL comes after ADATA.
+               // If we've seen an AGLOBL that said this sym was DUPOK,
+               // ignore any more ADATA we see, which must be
+               // redefinitions.
+               s = p->from.sym;
+               if(s != S && s->dupok) {
+                       if(debug['v'])
+                               Bprint(&bso, "skipping %s in %s: dupok", s->name, pn);
+                       goto loop;
+               }
+               if(s != S) {
+                       p->dlink = s->data;
+                       s->data = p;
+               }
                if(edatap == P)
                        datap = p;
                else
@@ -1056,19 +1074,7 @@ loop:
                        }
                        diag("%s: redefinition: %s\n%P", pn, s->name, p);
                }
-               s->type = STEXT;
-               s->value = pc;
-               lastp->link = p;
-               lastp = p;
-               p->pc = pc;
-               pc++;
-               if(textp == P) {
-                       textp = p;
-                       etextp = p;
-                       goto loop;
-               }
-               etextp->pcond = p;
-               etextp = p;
+               newtext(p, s);
                goto loop;
 
        case AFMOVF:
index 934f14e9bca8273a46a997f399443611b637e430..df5ba629fce002950ebf4f886e4ac14f45b8fd83 100644 (file)
@@ -388,9 +388,6 @@ Optab optab[] =
        { ACMPSB,       ynone,  Pb, 0xa6 },
        { ACMPSL,       ynone,  Px, 0xa7 },
        { ACMPSW,       ynone,  Pe, 0xa7 },
-       { ACMPXCHGB,    yrb_mb, Pm, 0xb0 },
-       { ACMPXCHGL,    yrl_ml, Pm, 0xb1 },
-       { ACMPXCHGW,    yrl_ml, Pm, 0xb1 },
        { ADAA,         ynone,  Px, 0x27 },
        { ADAS,         ynone,  Px, 0x2f },
        { ADATA },
@@ -688,5 +685,11 @@ Optab optab[] =
        { AFYL2X,       ynone,  Px, 0xd9, 0xf1 },
        { AFYL2XP1,     ynone,  Px, 0xd9, 0xf9 },
        { AEND },
+       { ADYNT },
+       { AINIT },
+       { ASIGNAME },
+       { ACMPXCHGB,    yrb_mb, Pm, 0xb0 },
+       { ACMPXCHGL,    yrl_ml, Pm, 0xb1 },
+       { ACMPXCHGW,    yrl_ml, Pm, 0xb1 },
        0
 };
index 0726d1ea8fcee0a918314e0096122de48eaf11c2..2e52edc0ccddea32c3a1ad99795c0f135a67b6b8 100644 (file)
@@ -802,7 +802,7 @@ ckoff(Sym *s, int32 v)
                diag("relocation offset %ld for %s out of range", v, s->name);
 }
 
-static Prog*
+Prog*
 newdata(Sym *s, int o, int w, int t)
 {
        Prog *p;
@@ -820,6 +820,30 @@ newdata(Sym *s, int o, int w, int t)
        p->from.sym = s;
        p->from.offset = o;
        p->to.type = D_CONST;
+       p->dlink = s->data;
+       s->data = p;
+       return p;
+}
+
+Prog*
+newtext(Prog *p, Sym *s)
+{
+       if(p == P) {
+               p = prg();
+               p->as = ATEXT;
+               p->from.sym = s;
+       }
+       s->type = STEXT;
+       s->text = p;
+       s->value = pc;
+       lastp->link = p;
+       lastp = p;
+       p->pc = pc++;
+       if(textp == P)
+               textp = p;
+       else
+               etextp->pcond = p;
+       etextp = p;
        return p;
 }
 
index 81703d3046af9ad8f290b8cd475d00e73d0ac840..6adf5295abb0b35e2979ba329db1169047f450f3 100644 (file)
@@ -146,12 +146,9 @@ xdefine(char *p, int t, int32 v)
 }
 
 void
-putsymb(char *s, int t, int32 v, int ver)
+putsymb(char *s, int t, int32 v, int ver, char *go)
 {
        int i, j, f;
-       char *go; 
-       
-       go = nil;       // TODO
 
        if(t == 'f')
                s++;
@@ -211,25 +208,25 @@ asmsym(void)
 
        s = lookup("etext", 0);
        if(s->type == STEXT)
-               putsymb(s->name, 'T', s->value, s->version);
+               putsymb(s->name, 'T', s->value, s->version, nil);
 
        for(h=0; h<NHASH; h++)
                for(s=hash[h]; s!=S; s=s->link)
                        switch(s->type) {
                        case SCONST:
-                               putsymb(s->name, 'D', s->value, s->version);
+                               putsymb(s->name, 'D', s->value, s->version, gotypefor(s->name));
                                continue;
 
                        case SDATA:
-                               putsymb(s->name, 'D', s->value+INITDAT, s->version);
+                               putsymb(s->name, 'D', s->value+INITDAT, s->version, gotypefor(s->name));
                                continue;
 
                        case SBSS:
-                               putsymb(s->name, 'B', s->value+INITDAT, s->version);
+                               putsymb(s->name, 'B', s->value+INITDAT, s->version, gotypefor(s->name));
                                continue;
 
                        case SFILE:
-                               putsymb(s->name, 'f', s->value, s->version);
+                               putsymb(s->name, 'f', s->value, s->version, nil);
                                continue;
                        }
 
@@ -241,22 +238,22 @@ asmsym(void)
                /* filenames first */
                for(a=p->to.autom; a; a=a->link)
                        if(a->type == D_FILE)
-                               putsymb(a->asym->name, 'z', a->aoffset, 0);
+                               putsymb(a->asym->name, 'z', a->aoffset, 0, nil);
                        else
                        if(a->type == D_FILE1)
-                               putsymb(a->asym->name, 'Z', a->aoffset, 0);
+                               putsymb(a->asym->name, 'Z', a->aoffset, 0, nil);
 
-               putsymb(s->name, 'T', s->value, s->version);
+               putsymb(s->name, 'T', s->value, s->version, gotypefor(s->name));
 
                /* frame, auto and param after */
-               putsymb(".frame", 'm', p->to.offset+4, 0);
+               putsymb(".frame", 'm', p->to.offset+4, 0, nil);
 
                for(a=p->to.autom; a; a=a->link)
                        if(a->type == D_AUTO)
-                               putsymb(a->asym->name, 'a', -a->aoffset, 0);
+                               putsymb(a->asym->name, 'a', -a->aoffset, 0, nil);
                        else
                        if(a->type == D_PARAM)
-                               putsymb(a->asym->name, 'p', a->aoffset, 0);
+                               putsymb(a->asym->name, 'p', a->aoffset, 0, nil);
        }
        if(debug['v'] || debug['n'])
                Bprint(&bso, "symsize = %lud\n", symsize);
@@ -366,7 +363,7 @@ oclass(Adr *a)
 {
        int32 v;
 
-       if(a->type >= D_INDIR || a->index != D_NONE) {
+       if((a->type >= D_INDIR && a->type < 2*D_INDIR) || a->index != D_NONE) {
                if(a->index != D_NONE && a->scale == 0) {
                        if(a->type == D_ADDR) {
                                switch(a->index) {
@@ -615,7 +612,7 @@ asmand(Adr *a, int r)
        v = a->offset;
        t = a->type;
        if(a->index != D_NONE) {
-               if(t >= D_INDIR) {
+               if(t >= D_INDIR && t < 2*D_INDIR) {
                        t -= D_INDIR;
                        if(t == D_NONE) {
                                *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
@@ -663,7 +660,7 @@ asmand(Adr *a, int r)
                *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
                return;
        }
-       if(t >= D_INDIR) {
+       if(t >= D_INDIR && t < 2*D_INDIR) {
                t -= D_INDIR;
                if(t == D_NONE || (D_CS <= t && t <= D_GS)) {
                        *andptr++ = (0 << 6) | (5 << 0) | (r << 3);
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
new file mode 100644 (file)
index 0000000..e8366e8
--- /dev/null
@@ -0,0 +1,587 @@
+// Copyright 2009 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.
+
+// go-specific code shared across loaders (5l, 6l, 8l).
+
+// accumulate all type information from .6 files.
+// check for inconsistencies.
+// define gotypestrings variable if needed.
+// define gotypesigs variable if needed.
+
+// TODO:
+//     include type info for non-exported types.
+//     generate debugging section in binary.
+//     once the dust settles, try to move some code to
+//             libmach, so that other linkers and ar can share.
+
+/*
+ *     package import data
+ */
+typedef struct Import Import;
+struct Import
+{
+       Import *hash;   // next in hash table
+       int export;     // marked as export?
+       char *prefix;   // "type", "var", "func", "const"
+       char *name;
+       char *def;
+       char *file;
+};
+enum {
+       NIHASH = 1024
+};
+static Import *ihash[NIHASH];
+static int nimport;
+
+static int
+hashstr(char *name)
+{
+       int h;
+       char *cp;
+
+       h = 0;
+       for(cp = name; *cp; h += *cp++)
+               h *= 1119;
+       if(h < 0)
+               h = ~h;
+       return h;
+}
+
+static Import *
+ilookup(char *name)
+{
+       int h;
+       Import *x;
+
+       h = hashstr(name) % NIHASH;
+       for(x=ihash[h]; x; x=x->hash)
+               if(x->name[0] == name[0] && strcmp(x->name, name) == 0)
+                       return x;
+       x = mal(sizeof *x);
+       x->name = name;
+       x->hash = ihash[h];
+       ihash[h] = x;
+       nimport++;
+       return x;
+}
+
+char*
+gotypefor(char *name)
+{
+       Import *x;
+       char *s, *p;
+
+       s = strdup(name);
+       p = utfrune(s, 0xB7);   // center dot
+       if(p == nil)
+               return nil;
+       *p++ = '.';
+       memmove(p, p+1, strlen(p));
+       x = ilookup(s);
+       free(s);
+       if(x == nil || x->prefix == nil)
+               return nil;
+       if(strcmp(x->prefix, "var") != 0 && strcmp(x->prefix, "func") != 0)
+               return nil;
+       return x->def;
+}
+
+static void loadpkgdata(char*, char*, int);
+static int parsemethod(char**, char*, char**);
+static int parsepkgdata(char*, char**, char*, int*, char**, char**, char**);
+
+void
+ldpkg(Biobuf *f, int64 len, char *filename)
+{
+       char *data, *p0, *p1;
+
+       if(debug['g'])
+               return;
+
+       if((int)len != len) {
+               fprint(2, "6l: too much pkg data in %s\n", filename);
+               return;
+       }
+       data = mal(len);
+       if(Bread(f, data, len) != len) {
+               fprint(2, "6l: short pkg read %s\n", filename);
+               return;
+       }
+
+       // first \n$$ marks beginning of exports - skip rest of line
+       p0 = strstr(data, "\n$$");
+       if(p0 == nil)
+               return;
+       p0 += 3;
+       while(*p0 != '\n' && *p0 != '\0')
+               p0++;
+
+       // second marks end of exports / beginning of local data
+       p1 = strstr(p0, "\n$$");
+       if(p1 == nil) {
+               fprint(2, "6l: cannot find end of exports in %s\n", filename);
+               return;
+       }
+       while(*p0 == ' ' || *p0 == '\t' || *p0 == '\n')
+               p0++;
+       if(strncmp(p0, "package ", 8) != 0) {
+               fprint(2, "6l: bad package section in %s\n", filename);
+               return;
+       }
+       p0 += 8;
+       while(*p0 == ' ' || *p0 == '\t' || *p0 == '\n')
+               p0++;
+       while(*p0 != ' ' && *p0 != '\t' && *p0 != '\n')
+               p0++;
+
+       loadpkgdata(filename, p0, p1 - p0);
+
+       // local types begin where exports end.
+       // skip rest of line after $$ we found above
+       p0 = p1 + 3;
+       while(*p0 != '\n' && *p0 != '\0')
+               p0++;
+
+       // local types end at next \n$$.
+       p1 = strstr(p0, "\n$$");
+       if(p1 == nil) {
+               fprint(2, "6l: cannot find end of local types in %s\n", filename);
+               return;
+       }
+
+       loadpkgdata(filename, p0, p1 - p0);
+}
+
+static void
+loadpkgdata(char *file, char *data, int len)
+{
+       int export;
+       char *p, *ep, *prefix, *name, *def;
+       Import *x;
+
+       file = strdup(file);
+       p = data;
+       ep = data + len;
+       while(parsepkgdata(file, &p, ep, &export, &prefix, &name, &def) > 0) {
+               x = ilookup(name);
+               if(x->prefix == nil) {
+                       x->prefix = prefix;
+                       x->def = def;
+                       x->file = file;
+                       x->export = export;
+               } else {
+                       if(strcmp(x->prefix, prefix) != 0) {
+                               fprint(2, "6l: conflicting definitions for %s\n", name);
+                               fprint(2, "%s:\t%s %s ...\n", x->file, x->prefix, name);
+                               fprint(2, "%s:\t%s %s ...\n", file, prefix, name);
+                               nerrors++;
+                       }
+                       else if(strcmp(x->def, def) != 0) {
+                               fprint(2, "6l: conflicting definitions for %s\n", name);
+                               fprint(2, "%s:\t%s %s %s\n", x->file, x->prefix, name, x->def);
+                               fprint(2, "%s:\t%s %s %s\n", file, prefix, name, def);
+                               nerrors++;
+                       }
+
+                       // okay if some .6 say export and others don't.
+                       // all it takes is one.
+                       if(export)
+                               x->export = 1;
+               }
+       }
+}
+
+static int
+parsepkgdata(char *file, char **pp, char *ep, int *exportp, char **prefixp, char **namep, char **defp)
+{
+       char *p, *prefix, *name, *def, *edef, *meth;
+       int n;
+
+       // skip white space
+       p = *pp;
+       while(p < ep && (*p == ' ' || *p == '\t' || *p == '\n'))
+               p++;
+       if(p == ep || strncmp(p, "$$\n", 3) == 0)
+               return 0;
+
+       // [export|package ]
+       *exportp = 0;
+       if(p + 7 <= ep && strncmp(p, "export ", 7) == 0) {
+               *exportp = 1;
+               p += 7;
+       }
+       else if(p + 8 <= ep && strncmp(p, "package ", 8) == 0) {
+               *exportp = 2;
+               p += 8;
+       }
+
+       // prefix: (var|type|func|const)
+       prefix = p;
+
+       prefix = p;
+       if(p + 6 > ep)
+               return -1;
+       if(strncmp(p, "var ", 4) == 0)
+               p += 4;
+       else if(strncmp(p, "type ", 5) == 0)
+               p += 5;
+       else if(strncmp(p, "func ", 5) == 0)
+               p += 5;
+       else if(strncmp(p, "const ", 6) == 0)
+               p += 6;
+       else{
+               fprint(2, "6l: confused in pkg data near <<%.20s>>\n", p);
+               nerrors++;
+               return -1;
+       }
+       p[-1] = '\0';
+
+       // name: a.b followed by space
+       name = p;
+       while(p < ep && *p != ' ')
+               p++;
+       if(p >= ep)
+               return -1;
+       *p++ = '\0';
+
+       // def: free form to new line
+       def = p;
+       while(p < ep && *p != '\n')
+               p++;
+       if(p >= ep)
+               return -1;
+       edef = p;
+       *p++ = '\0';
+
+       // include methods on successive lines in def of named type
+       while(parsemethod(&p, ep, &meth) > 0) {
+               *edef++ = '\n'; // overwrites '\0'
+               if(edef+1 > meth) {
+                       // We want to indent methods with a single \t.
+                       // 6g puts at least one char of indent before all method defs,
+                       // so there will be room for the \t.  If the method def wasn't
+                       // indented we could do something more complicated,
+                       // but for now just diagnose the problem and assume
+                       // 6g will keep indenting for us.
+                       fprint(2, "6l: %s: expected methods to be indented %p %p %.10s\n",
+                               file, edef, meth, meth);
+                       nerrors++;
+                       return -1;
+               }
+               *edef++ = '\t';
+               n = strlen(meth);
+               memmove(edef, meth, n);
+               edef += n;
+       }
+
+       // done
+       *pp = p;
+       *prefixp = prefix;
+       *namep = name;
+       *defp = def;
+       return 1;
+}
+
+static int
+parsemethod(char **pp, char *ep, char **methp)
+{
+       char *p;
+
+       // skip white space
+       p = *pp;
+       while(p < ep && (*p == ' ' || *p == '\t'))
+               p++;
+       if(p == ep)
+               return 0;
+
+       // if it says "func (", it's a method
+       if(p + 6 >= ep || strncmp(p, "func (", 6) != 0)
+               return 0;
+
+       // definition to end of line
+       *methp = p;
+       while(p < ep && *p != '\n')
+               p++;
+       if(p >= ep) {
+               fprint(2, "6l: lost end of line in method definition\n");
+               *pp = ep;
+               return -1;
+       }
+       *p++ = '\0';
+       *pp = p;
+       return 1;
+}
+
+static int
+importcmp(const void *va, const void *vb)
+{
+       Import *a, *b;
+
+       a = *(Import**)va;
+       b = *(Import**)vb;
+       return strcmp(a->name, b->name);
+}
+
+static int
+symcmp(const void *va, const void *vb)
+{
+       Sym *a, *b;
+
+       a = *(Sym**)va;
+       b = *(Sym**)vb;
+       return strcmp(a->name, b->name);
+}
+
+// if there is an undefined reference to gotypestrings,
+// create it.  c declaration is
+//     extern char gotypestrings[];
+// ironically, gotypestrings is a c variable, because there
+// is no way to forward declare a string in go.
+void
+definetypestrings(void)
+{
+       int i, j, len, n, w;
+       char *p;
+       Import **all, *x;
+       Fmt f;
+       Prog *prog;
+       Sym *s;
+
+       if(debug['g'])
+               return;
+
+       if(debug['v'])
+               Bprint(&bso, "%5.2f definetypestrings\n", cputime());
+
+       s = lookup("gotypestrings", 0);
+       if(s->type == 0)
+               return;
+       if(s->type != SXREF) {
+               diag("gotypestrings already defined");
+               return;
+       }
+       s->type = SDATA;
+
+       // make a list of all the type exports
+       n = 0;
+       for(i=0; i<NIHASH; i++)
+               for(x=ihash[i]; x; x=x->hash)
+                       if(strcmp(x->prefix, "type") == 0)
+                               n++;
+       all = mal(n*sizeof all[0]);
+       j = 0;
+       for(i=0; i<NIHASH; i++)
+               for(x=ihash[i]; x; x=x->hash)
+                       if(strcmp(x->prefix, "type") == 0)
+                               all[j++] = x;
+
+       // sort them by name
+       qsort(all, n, sizeof all[0], importcmp);
+
+       // make a big go string containing all the types
+       fmtstrinit(&f);
+       fmtprint(&f, "xxxx");   // 4-byte length
+       for(i=0; i<n; i++) {
+               p = strchr(all[i]->def, '\n');
+               if(p)
+                       len = p - all[i]->def;
+               else
+                       len = strlen(all[i]->def);
+               fmtprint(&f, "%s %.*s\n", all[i]->name, utfnlen(all[i]->def, len), all[i]->def);
+       }
+       p = fmtstrflush(&f);
+       n = strlen(p);
+       s->value = n;
+
+       // go strings begin with 4-byte length.
+       // amd64 is little-endian.
+       len = n - 4;
+       p[0] = len;
+       p[1] = len >> 8;
+       p[2] = len >> 16;
+       p[3] = len >> 24;
+
+       // have data, need to create linker representation.
+       // linker stores big data as sequence of pieces
+       // with int8 length, so break p into 100-byte chunks.
+       // (had to add D_SBIG even to do that; the compiler
+       // would have generated 8-byte chunks.)
+       for(i=0; i<n; i+=100) {
+               w = 100;
+               if(w > n - i)
+                       w = n - i;
+               prog = newdata(s, i, w, D_EXTERN);
+               prog->to.type = D_SBIG;
+               prog->to.sbig = p + i;
+       }
+
+       if(debug['v'])
+               Bprint(&bso, "%5.2f typestrings %d\n", cputime(), n);
+}
+
+// if there is an undefined reference to gotypesigs, create it.
+// c declaration is
+//     extern Sigt *gotypesigs[];
+//     extern int ngotypesigs;
+// used by sys.unreflect runtime.
+void
+definetypesigs(void)
+{
+       int i, j, n;
+       Sym **all, *s, *x;
+       Prog *prog;
+
+       if(debug['g'])
+               return;
+
+       if(debug['v'])
+               Bprint(&bso, "%5.2f definetypesigs\n", cputime());
+
+       s = lookup("gotypesigs", 0);
+       if(s->type == 0)
+               return;
+       if(s->type != SXREF) {
+               diag("gotypesigs already defined");
+               return;
+       }
+       s->type = SDATA;
+
+       // make a list of all the sigt symbols.
+       n = 0;
+       for(i=0; i<NHASH; i++)
+               for(x = hash[i]; x; x=x->link)
+                       if(memcmp(x->name, "sigt·", 6) == 0 && x->type != Sxxx)
+                               n++;
+       all = mal(n*sizeof all[0]);
+       j = 0;
+       for(i=0; i<NHASH; i++)
+               for(x = hash[i]; x; x=x->link)
+                       if(memcmp(x->name, "sigt·", 6) == 0 && x->type != Sxxx)
+                               all[j++] = x;
+
+       // sort them by name
+       qsort(all, n, sizeof all[0], symcmp);
+
+       // emit array as sequence of references.
+       enum { PtrSize = 8 };
+       for(i=0; i<n; i++) {
+               prog = newdata(s, PtrSize*i, PtrSize, D_EXTERN);
+               prog->to.type = D_ADDR;
+               prog->to.index = D_EXTERN;
+               prog->to.sym = all[i];
+       }
+       s->value = PtrSize*n;
+       if(n == 0)
+               s->value = 1;   // must have non-zero size or 6l complains
+
+       // emit count
+       s = lookup("ngotypesigs", 0);
+       s->type = SDATA;
+       s->value = sizeof(int32);
+       prog = newdata(s, 0, sizeof(int32), D_EXTERN);
+       prog->to.offset = n;
+
+       if(debug['v'])
+               Bprint(&bso, "%5.2f typesigs %d\n", cputime(), n);
+}
+
+static void mark(Sym*);
+static int markdepth;
+
+static void
+markdata(Prog *p, Sym *s)
+{
+       markdepth++;
+       if(p != P && debug['v'] > 1)
+               Bprint(&bso, "%d markdata %s\n", markdepth, s->name);
+       for(; p != P; p=p->dlink)
+               if(p->to.sym)
+                       mark(p->to.sym);
+       markdepth--;
+}
+
+static void
+marktext(Prog *p)
+{
+       if(p == P)
+               return;
+       if(p->as != ATEXT) {
+               diag("marktext: %P", p);
+               return;
+       }
+       markdepth++;
+       if(debug['v'] > 1)
+               Bprint(&bso, "%d marktext %s\n", markdepth, p->from.sym->name);
+       for(p=p->link; p != P; p=p->link) {
+               if(p->as == ATEXT || p->as == ADATA || p->as == AGLOBL)
+                       break;
+               if(p->from.sym)
+                       mark(p->from.sym);
+               if(p->to.sym)
+                       mark(p->to.sym);
+       }
+       markdepth--;
+}
+
+static void
+mark(Sym *s)
+{
+       if(s == S || s->reachable)
+               return;
+       s->reachable = 1;
+       if(s->text)
+               marktext(s->text);
+       if(s->data)
+               markdata(s->data, s);
+}
+
+static void
+sweeplist(Prog **first, Prog **last)
+{
+       int reachable;
+       Prog *p, *q;
+
+       reachable = 1;
+       q = P;
+       for(p=*first; p != P; p=p->link) {
+               switch(p->as) {
+               case ATEXT:
+               case ADATA:
+               case AGLOBL:
+                       reachable = p->from.sym->reachable;
+                       if(!reachable) {
+                               if(debug['v'] > 1)
+                                       Bprint(&bso, "discard %s\n", p->from.sym->name);
+                               p->from.sym->type = Sxxx;
+                       }
+                       break;
+               }
+               if(reachable) {
+                       if(q == P)
+                               *first = p;
+                       else
+                               q->link = p;
+                       q = p;
+               }
+       }
+       if(q == P)
+               *first = P;
+       else
+               q->link = P;
+       *last = q;
+}
+
+void
+deadcode(void)
+{
+       if(debug['v'])
+               Bprint(&bso, "%5.2f deadcode\n", cputime());
+
+       mark(lookup(INITENTRY, 0));
+       mark(lookup("sys·morestack", 0));
+
+//     sweeplist(&firstp, &lastp);
+//     sweeplist(&datap, &edatap);
+}
+