void slicebytes(Node *nam, char *s, int len) { int off, n, m; static int gen; Sym *sym; snprint(namebuf, sizeof(namebuf), ".gobytes.%d", ++gen); sym = pkglookup(namebuf, localpkg); sym->def = newname(sym); off = 0; for(n=0; n<len; n+=m) { m = 8; if(m > len-n) m = len-n; off = dsname(sym, off, s+n, m); } ggloblsym(sym, off, 0, 0); if(nam->op != ONAME) fatal("slicebytes %N", nam); off = nam->xoffset; off = dsymptr(nam->sym, off, sym, 0); off = duintxx(nam->sym, off, len, widthint); duintxx(nam->sym, off, len, widthint); }
static void dumpglobls(void) { Node *n; NodeList *l; // add globals for(l=externdcl; l; l=l->next) { n = l->n; if(n->op != ONAME) continue; if(n->type == T) fatal("external %N nil type\n", n); if(n->class == PFUNC) continue; if(n->sym->pkg != localpkg) continue; dowidth(n->type); ggloblnod(n); } for(l=funcsyms; l; l=l->next) { n = l->n; dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0); ggloblsym(n->sym, widthptr, 1, 1); } // Do not reprocess funcsyms on next dumpglobls call. funcsyms = nil; }
Sym* stringsym(char *s, int len) { static int gen; Sym *sym; int off, n, m; struct { Strlit lit; char buf[110]; } tmp; Pkg *pkg; if(len > 100) { // huge strings are made static to avoid long names snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen); pkg = localpkg; } else { // small strings get named by their contents, // so that multiple modules using the same string // can share it. tmp.lit.len = len; memmove(tmp.lit.s, s, len); tmp.lit.s[len] = '\0'; snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit); pkg = gostringpkg; } sym = pkglookup(namebuf, pkg); // SymUniq flag indicates that data is generated already if(sym->flags & SymUniq) return sym; sym->flags |= SymUniq; sym->def = newname(sym); off = 0; // string header off = dsymptr(sym, off, sym, widthptr+widthint); off = duintxx(sym, off, len, widthint); // string data for(n=0; n<len; n+=m) { m = 8; if(m > len-n) m = len-n; off = dsname(sym, off, s+n, m); } off = duint8(sym, off, 0); // terminating NUL for runtime off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment ggloblsym(sym, off, 1, 1); return sym; }
void dumpobj(void) { NodeList *externs, *tmp; char arhdr[ArhdrSize]; vlong startobj, size; Sym *zero; bout = Bopen(outfile, OWRITE); if(bout == nil) { flusherrors(); print("can't create %s: %r\n", outfile); errorexit(); } startobj = 0; if(writearchive) { Bwrite(bout, "!<arch>\n", 8); memset(arhdr, 0, sizeof arhdr); Bwrite(bout, arhdr, sizeof arhdr); startobj = Boffset(bout); } Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring()); dumpexport(); if(writearchive) { Bflush(bout); size = Boffset(bout) - startobj; if(size&1) Bputc(bout, 0); Bseek(bout, startobj - ArhdrSize, 0); formathdr(arhdr, "__.PKGDEF", size); Bwrite(bout, arhdr, ArhdrSize); Bflush(bout); Bseek(bout, startobj + size + (size&1), 0); memset(arhdr, 0, ArhdrSize); Bwrite(bout, arhdr, ArhdrSize); startobj = Boffset(bout); Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring()); } Bprint(bout, "\n!\n"); externs = nil; if(externdcl != nil) externs = externdcl->end; dumpglobls(); dumptypestructs(); // Dump extra globals. tmp = externdcl; if(externs != nil) externdcl = externs->next; dumpglobls(); externdcl = tmp; zero = pkglookup("zerovalue", runtimepkg); ggloblsym(zero, zerosize, 1, 1); dumpdata(); writeobj(ctxt, bout); if(writearchive) { Bflush(bout); size = Boffset(bout) - startobj; if(size&1) Bputc(bout, 0); Bseek(bout, startobj - ArhdrSize, 0); snprint(namebuf, sizeof namebuf, "_go_.%c", thechar); formathdr(arhdr, namebuf, size); Bwrite(bout, arhdr, ArhdrSize); } Bterm(bout); }
/* * make a refer to the string sval, * emitting DATA if needed. */ void datagostring(Strlit *sval, Addr *a) { Prog *p; Addr ac, ao, ap; int32 wi, wp; static int gen; memset(&ac, 0, sizeof(ac)); memset(&ao, 0, sizeof(ao)); memset(&ap, 0, sizeof(ap)); // constant ac.type = D_CONST; ac.name = D_NONE; ac.offset = 0; // fill in ac.reg = NREG; // string len+ptr ao.type = D_OREG; ao.name = D_STATIC; // fill in ao.etype = TINT32; ao.sym = nil; // fill in ao.reg = NREG; // $string len+ptr datastring(sval->s, sval->len, &ap); ap.type = D_CONST; ap.etype = TINT32; wi = types[TUINT32]->width; wp = types[tptr]->width; if(ap.name == D_STATIC) { // huge strings are made static to avoid long names snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen); ao.sym = lookup(namebuf); ao.name = D_STATIC; } else { // small strings get named by their contents, // so that multiple modules using the same string // can share it. snprint(namebuf, sizeof(namebuf), "\"%Z\"", sval); ao.sym = pkglookup(namebuf, gostringpkg); ao.name = D_EXTERN; } *a = ao; if(ao.sym->flags & SymUniq) return; ao.sym->flags |= SymUniq; data(); // DATA gostring, wp, $cstring p = pc; gins(ADATA, N, N); p->from = ao; p->reg = wp; p->to = ap; // DATA gostring+wp, wi, $len p = pc; gins(ADATA, N, N); p->from = ao; p->from.offset = wp; p->reg = wi; p->to = ac; p->to.offset = sval->len; p = pc; ggloblsym(ao.sym, types[TSTRING]->width, ao.name == D_EXTERN); if(ao.name == D_STATIC) p->from.name = D_STATIC; text(); }
/* * make a refer to the data s, s+len * emitting DATA if needed. */ void datastring(char *s, int len, Addr *a) { int w; Prog *p; Addr ac, ao; static int gen; struct { Strlit lit; char buf[100]; } tmp; // string memset(&ao, 0, sizeof(ao)); ao.type = D_OREG; ao.name = D_STATIC; ao.etype = TINT32; ao.offset = 0; // fill in ao.reg = NREG; // constant memset(&ac, 0, sizeof(ac)); ac.type = D_CONST; ac.name = D_NONE; ac.offset = 0; // fill in ac.reg = NREG; // huge strings are made static to avoid long names. if(len > 100) { snprint(namebuf, sizeof(namebuf), ".string.%d", gen++); ao.sym = lookup(namebuf); ao.name = D_STATIC; } else { if(len > 0 && s[len-1] == '\0') len--; tmp.lit.len = len; memmove(tmp.lit.s, s, len); tmp.lit.s[len] = '\0'; len++; snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit); ao.sym = pkglookup(namebuf, stringpkg); ao.name = D_EXTERN; } *a = ao; // only generate data the first time. if(ao.sym->flags & SymUniq) return; ao.sym->flags |= SymUniq; data(); for(w=0; w<len; w+=8) { p = pc; gins(ADATA, N, N); // DATA s+w, [NSNAME], $"xxx" p->from = ao; p->from.offset = w; p->reg = NSNAME; if(w+8 > len) p->reg = len-w; p->to = ac; p->to.type = D_SCONST; p->to.offset = len; memmove(p->to.sval, s+w, p->reg); } p = pc; ggloblsym(ao.sym, len, ao.name == D_EXTERN); if(ao.name == D_STATIC) p->from.name = D_STATIC; text(); }