// p is a call instruction. Does the call fail to return? int noreturn(Prog *p) { Sym *s; int i; static Sym* symlist[10]; if(symlist[0] == S) { symlist[0] = pkglookup("panicindex", runtimepkg); symlist[1] = pkglookup("panicslice", runtimepkg); symlist[2] = pkglookup("throwinit", runtimepkg); symlist[3] = pkglookup("panic", runtimepkg); symlist[4] = pkglookup("panicwrap", runtimepkg); symlist[5] = pkglookup("throwreturn", runtimepkg); symlist[6] = pkglookup("selectgo", runtimepkg); symlist[7] = pkglookup("block", runtimepkg); } if(p->to.node == nil) return 0; s = p->to.node->sym; if(s == S) return 0; for(i=0; symlist[i]!=S; i++) if(s == symlist[i]) return 1; return 0; }
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); }
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; }
int noreturn(Prog *p) { Sym *s; int i; if(symlist[0] == S) { symlist[0] = pkglookup("panicindex", runtimepkg); symlist[1] = pkglookup("panicslice", runtimepkg); symlist[2] = pkglookup("throwinit", runtimepkg); symlist[3] = pkglookup("panic", runtimepkg); } s = p->to.sym; if(s == S) return 0; for(i=0; symlist[i]!=S; i++) if(s == symlist[i]) return 1; return 0; }
void typeinit(void) { int i, etype, sameas; Type *t; Sym *s, *s1; if(widthptr == 0) fatal("typeinit before betypeinit"); for(i=0; i<NTYPE; i++) simtype[i] = i; types[TPTR32] = typ(TPTR32); dowidth(types[TPTR32]); types[TPTR64] = typ(TPTR64); dowidth(types[TPTR64]); t = typ(TUNSAFEPTR); types[TUNSAFEPTR] = t; t->sym = pkglookup("Pointer", unsafepkg); t->sym->def = typenod(t); dowidth(types[TUNSAFEPTR]); tptr = TPTR32; if(widthptr == 8) tptr = TPTR64; for(i=TINT8; i<=TUINT64; i++) isint[i] = 1; isint[TINT] = 1; isint[TUINT] = 1; isint[TUINTPTR] = 1; isfloat[TFLOAT32] = 1; isfloat[TFLOAT64] = 1; iscomplex[TCOMPLEX64] = 1; iscomplex[TCOMPLEX128] = 1; isptr[TPTR32] = 1; isptr[TPTR64] = 1; isforw[TFORW] = 1; issigned[TINT] = 1; issigned[TINT8] = 1; issigned[TINT16] = 1; issigned[TINT32] = 1; issigned[TINT64] = 1; /* * initialize okfor */ for(i=0; i<NTYPE; i++) { if(isint[i] || i == TIDEAL) { okforeq[i] = 1; okforcmp[i] = 1; okforarith[i] = 1; okforadd[i] = 1; okforand[i] = 1; okforconst[i] = 1; issimple[i] = 1; minintval[i] = mal(sizeof(*minintval[i])); maxintval[i] = mal(sizeof(*maxintval[i])); } if(isfloat[i]) { okforeq[i] = 1; okforcmp[i] = 1; okforadd[i] = 1; okforarith[i] = 1; okforconst[i] = 1; issimple[i] = 1; minfltval[i] = mal(sizeof(*minfltval[i])); maxfltval[i] = mal(sizeof(*maxfltval[i])); } if(iscomplex[i]) { okforeq[i] = 1; okforadd[i] = 1; okforarith[i] = 1; okforconst[i] = 1; issimple[i] = 1; } } issimple[TBOOL] = 1; okforadd[TSTRING] = 1; okforbool[TBOOL] = 1; okforcap[TARRAY] = 1; okforcap[TCHAN] = 1; okforconst[TBOOL] = 1; okforconst[TSTRING] = 1; okforlen[TARRAY] = 1; okforlen[TCHAN] = 1; okforlen[TMAP] = 1; okforlen[TSTRING] = 1; okforeq[TPTR32] = 1; okforeq[TPTR64] = 1; okforeq[TUNSAFEPTR] = 1; okforeq[TINTER] = 1; okforeq[TCHAN] = 1; okforeq[TSTRING] = 1; okforeq[TBOOL] = 1; okforeq[TMAP] = 1; // nil only; refined in typecheck okforeq[TFUNC] = 1; // nil only; refined in typecheck okforeq[TARRAY] = 1; // nil slice only; refined in typecheck okforeq[TSTRUCT] = 1; // it's complicated; refined in typecheck okforcmp[TSTRING] = 1; for(i=0; i<nelem(okfor); i++) okfor[i] = okfornone; // binary okfor[OADD] = okforadd; okfor[OAND] = okforand; okfor[OANDAND] = okforbool; okfor[OANDNOT] = okforand; okfor[ODIV] = okforarith; okfor[OEQ] = okforeq; okfor[OGE] = okforcmp; okfor[OGT] = okforcmp; okfor[OLE] = okforcmp; okfor[OLT] = okforcmp; okfor[OMOD] = okforand; okfor[OMUL] = okforarith; okfor[ONE] = okforeq; okfor[OOR] = okforand; okfor[OOROR] = okforbool; okfor[OSUB] = okforarith; okfor[OXOR] = okforand; okfor[OLSH] = okforand; okfor[ORSH] = okforand; // unary okfor[OCOM] = okforand; okfor[OMINUS] = okforarith; okfor[ONOT] = okforbool; okfor[OPLUS] = okforarith; // special okfor[OCAP] = okforcap; okfor[OLEN] = okforlen; // comparison iscmp[OLT] = 1; iscmp[OGT] = 1; iscmp[OGE] = 1; iscmp[OLE] = 1; iscmp[OEQ] = 1; iscmp[ONE] = 1; mpatofix(maxintval[TINT8], "0x7f"); mpatofix(minintval[TINT8], "-0x80"); mpatofix(maxintval[TINT16], "0x7fff"); mpatofix(minintval[TINT16], "-0x8000"); mpatofix(maxintval[TINT32], "0x7fffffff"); mpatofix(minintval[TINT32], "-0x80000000"); mpatofix(maxintval[TINT64], "0x7fffffffffffffff"); mpatofix(minintval[TINT64], "-0x8000000000000000"); mpatofix(maxintval[TUINT8], "0xff"); mpatofix(maxintval[TUINT16], "0xffff"); mpatofix(maxintval[TUINT32], "0xffffffff"); mpatofix(maxintval[TUINT64], "0xffffffffffffffff"); /* f is valid float if min < f < max. (min and max are not themselves valid.) */ mpatoflt(maxfltval[TFLOAT32], "33554431p103"); /* 2^24-1 p (127-23) + 1/2 ulp*/ mpatoflt(minfltval[TFLOAT32], "-33554431p103"); mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970"); /* 2^53-1 p (1023-52) + 1/2 ulp */ mpatoflt(minfltval[TFLOAT64], "-18014398509481983p970"); maxfltval[TCOMPLEX64] = maxfltval[TFLOAT32]; minfltval[TCOMPLEX64] = minfltval[TFLOAT32]; maxfltval[TCOMPLEX128] = maxfltval[TFLOAT64]; minfltval[TCOMPLEX128] = minfltval[TFLOAT64]; /* for walk to use in error messages */ types[TFUNC] = functype(N, nil, nil); /* types used in front end */ // types[TNIL] got set early in lexinit types[TIDEAL] = typ(TIDEAL); types[TINTER] = typ(TINTER); /* simple aliases */ simtype[TMAP] = tptr; simtype[TCHAN] = tptr; simtype[TFUNC] = tptr; simtype[TUNSAFEPTR] = tptr; /* pick up the backend typedefs */ for(i=0; typedefs[i].name; i++) { s = lookup(typedefs[i].name); s1 = pkglookup(typedefs[i].name, builtinpkg); etype = typedefs[i].etype; if(etype < 0 || etype >= nelem(types)) fatal("typeinit: %s bad etype", s->name); sameas = typedefs[i].sameas; if(sameas < 0 || sameas >= nelem(types)) fatal("typeinit: %s bad sameas", s->name); simtype[etype] = sameas; minfltval[etype] = minfltval[sameas]; maxfltval[etype] = maxfltval[sameas]; minintval[etype] = minintval[sameas]; maxintval[etype] = maxintval[sameas]; t = types[etype]; if(t != T) fatal("typeinit: %s already defined", s->name); t = typ(etype); t->sym = s1; dowidth(t); types[etype] = t; s1->def = typenod(t); } Array_array = rnd(0, widthptr); Array_nel = rnd(Array_array+widthptr, widthint); Array_cap = rnd(Array_nel+widthint, widthint); sizeof_Array = rnd(Array_cap+widthint, widthptr); // string is same as slice wo the cap sizeof_String = rnd(Array_nel+widthint, widthptr); dowidth(types[TSTRING]); dowidth(idealstring); }
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(); }
void typeinit(void) { int i, etype, sameas; Type *t; Sym *s, *s1; if(widthptr == 0) fatal("typeinit before betypeinit"); for(i=0; i<NTYPE; i++) simtype[i] = i; types[TPTR32] = typ(TPTR32); dowidth(types[TPTR32]); types[TPTR64] = typ(TPTR64); dowidth(types[TPTR64]); tptr = TPTR32; if(widthptr == 8) tptr = TPTR64; for(i=TINT8; i<=TUINT64; i++) isint[i] = 1; isint[TINT] = 1; isint[TUINT] = 1; isint[TUINTPTR] = 1; for(i=TFLOAT32; i<=TFLOAT64; i++) isfloat[i] = 1; isfloat[TFLOAT] = 1; isptr[TPTR32] = 1; isptr[TPTR64] = 1; isforw[TFORW] = 1; issigned[TINT] = 1; issigned[TINT8] = 1; issigned[TINT16] = 1; issigned[TINT32] = 1; issigned[TINT64] = 1; /* * initialize okfor */ for(i=0; i<NTYPE; i++) { if(isint[i] || i == TIDEAL) { okforeq[i] = 1; okforcmp[i] = 1; okforarith[i] = 1; okforadd[i] = 1; okforand[i] = 1; issimple[i] = 1; minintval[i] = mal(sizeof(*minintval[i])); maxintval[i] = mal(sizeof(*maxintval[i])); } if(isfloat[i]) { okforeq[i] = 1; okforcmp[i] = 1; okforadd[i] = 1; okforarith[i] = 1; issimple[i] = 1; minfltval[i] = mal(sizeof(*minfltval[i])); maxfltval[i] = mal(sizeof(*maxfltval[i])); } } issimple[TBOOL] = 1; okforadd[TSTRING] = 1; okforbool[TBOOL] = 1; okforcap[TARRAY] = 1; okforcap[TCHAN] = 1; okforlen[TARRAY] = 1; okforlen[TCHAN] = 1; okforlen[TMAP] = 1; okforlen[TSTRING] = 1; okforeq[TPTR32] = 1; okforeq[TPTR64] = 1; okforeq[TINTER] = 1; okforeq[TMAP] = 1; okforeq[TCHAN] = 1; okforeq[TFUNC] = 1; okforeq[TSTRING] = 1; okforeq[TBOOL] = 1; okforeq[TARRAY] = 1; // refined in typecheck okforcmp[TSTRING] = 1; for(i=0; i<nelem(okfor); i++) okfor[i] = okfornone; // binary okfor[OADD] = okforadd; okfor[OAND] = okforand; okfor[OANDAND] = okforbool; okfor[OANDNOT] = okforand; okfor[ODIV] = okforarith; okfor[OEQ] = okforeq; okfor[OGE] = okforcmp; okfor[OGT] = okforcmp; okfor[OLE] = okforcmp; okfor[OLT] = okforcmp; okfor[OMOD] = okforarith; okfor[OMUL] = okforarith; okfor[ONE] = okforeq; okfor[OOR] = okforand; okfor[OOROR] = okforbool; okfor[OSUB] = okforarith; okfor[OXOR] = okforand; okfor[OLSH] = okforand; okfor[ORSH] = okforand; // unary okfor[OCOM] = okforand; okfor[OMINUS] = okforarith; okfor[ONOT] = okforbool; okfor[OPLUS] = okforadd; // special okfor[OCAP] = okforcap; okfor[OLEN] = okforlen; // comparison iscmp[OLT] = 1; iscmp[OGT] = 1; iscmp[OGE] = 1; iscmp[OLE] = 1; iscmp[OEQ] = 1; iscmp[ONE] = 1; mpatofix(maxintval[TINT8], "0x7f"); mpatofix(minintval[TINT8], "-0x80"); mpatofix(maxintval[TINT16], "0x7fff"); mpatofix(minintval[TINT16], "-0x8000"); mpatofix(maxintval[TINT32], "0x7fffffff"); mpatofix(minintval[TINT32], "-0x80000000"); mpatofix(maxintval[TINT64], "0x7fffffffffffffff"); mpatofix(minintval[TINT64], "-0x8000000000000000"); mpatofix(maxintval[TUINT8], "0xff"); mpatofix(maxintval[TUINT16], "0xffff"); mpatofix(maxintval[TUINT32], "0xffffffff"); mpatofix(maxintval[TUINT64], "0xffffffffffffffff"); mpatoflt(maxfltval[TFLOAT32], "3.40282347e+38"); mpatoflt(minfltval[TFLOAT32], "-3.40282347e+38"); mpatoflt(maxfltval[TFLOAT64], "1.7976931348623157e+308"); mpatoflt(minfltval[TFLOAT64], "-1.7976931348623157e+308"); /* for walk to use in error messages */ types[TFUNC] = functype(N, nil, nil); /* types used in front end */ // types[TNIL] got set early in lexinit types[TIDEAL] = typ(TIDEAL); /* simple aliases */ simtype[TMAP] = tptr; simtype[TCHAN] = tptr; simtype[TFUNC] = tptr; /* pick up the backend typedefs */ for(i=0; typedefs[i].name; i++) { s = lookup(typedefs[i].name); s1 = pkglookup(typedefs[i].name, "/builtin/"); etype = typedefs[i].etype; if(etype < 0 || etype >= nelem(types)) fatal("typeinit: %s bad etype", s->name); sameas = typedefs[i].sameas; if(sameas < 0 || sameas >= nelem(types)) fatal("typeinit: %s bad sameas", s->name); simtype[etype] = sameas; minfltval[etype] = minfltval[sameas]; maxfltval[etype] = maxfltval[sameas]; minintval[etype] = minintval[sameas]; maxintval[etype] = maxintval[sameas]; t = types[etype]; if(t != T) fatal("typeinit: %s already defined", s->name); t = typ(etype); t->sym = s; dowidth(t); types[etype] = t; s1->def = typenod(t); } Array_array = rnd(0, widthptr); Array_nel = rnd(Array_array+widthptr, types[TUINT32]->width); Array_cap = rnd(Array_nel+types[TUINT32]->width, types[TUINT32]->width); sizeof_Array = rnd(Array_cap+types[TUINT32]->width, maxround); // string is same as slice wo the cap sizeof_String = rnd(Array_nel+types[TUINT32]->width, maxround); dowidth(types[TSTRING]); dowidth(idealstring); }