diff options
| author | 2025-12-15 22:39:52 +0100 | |
|---|---|---|
| committer | 2025-12-15 22:39:52 +0100 | |
| commit | 302e24671942051d70707586cf8c605a5815edac (patch) | |
| tree | 51e25fb6cd7e828c82ce5f17ffc775117121acee | |
| parent | c6c0f2ef35175075e91169113cfe856f29b3eb9a (diff) | |
create distinct interned string type
Interned strings are used pervasively, so it's a good idea to add a
layer of type safety to differentiate them from general cstrs and avoid
potential bugs from comparing non-interned and interned strings. Not
that that's happened so far that I can remember, but it could.
I'm 90% sure it's legal to alias `struct {char c;}` pointers with `char`
pointers. This specific typedef gives type safety but with a simple
one-way `internstr -> const char *` typecast (with `&istr->c`).
Converting the other way around is more intentional: a straight up cast
`(internstr)cstr` which sticks out as unchecked and probably wrong, or
calling the intern(cstr) function, which is the right way.
| -rw-r--r-- | c/c.c | 101 | ||||
| -rw-r--r-- | c/c.h | 4 | ||||
| -rw-r--r-- | c/lex.c | 43 | ||||
| -rw-r--r-- | c/lex.h | 3 | ||||
| -rw-r--r-- | common.h | 7 | ||||
| -rw-r--r-- | io.c | 12 | ||||
| -rw-r--r-- | ir/intrin.c | 2 | ||||
| -rw-r--r-- | ir/ir.c | 6 | ||||
| -rw-r--r-- | ir/ir.h | 12 | ||||
| -rw-r--r-- | mem.c | 6 | ||||
| -rw-r--r-- | obj/elf.c | 14 | ||||
| -rw-r--r-- | obj/obj.c | 14 | ||||
| -rw-r--r-- | obj/obj.h | 8 | ||||
| -rw-r--r-- | type.c | 10 | ||||
| -rw-r--r-- | type.h | 12 | ||||
| -rw-r--r-- | x86_64/emit.c | 6 |
16 files changed, 131 insertions, 129 deletions
@@ -113,13 +113,13 @@ struct declstate { call pdecl() to advance state before checking .more */ tagdecl, /* declarator is a tagged type */ empty; /* nothing decl (';') */ - const char **pnames; /* param names for function definition */ + internstr *pnames; /* param names for function definition */ struct span *pspans; /* param spans ditto */ uchar *pqual; /* param quals ditto */ }; static struct decl pdecl(struct declstate *st, struct comp *cm); -static struct decl *finddecl(struct comp *cm, const char *name); +static struct decl *finddecl(struct comp *cm, internstr name); /* next token starts a decl? */ static bool @@ -127,7 +127,7 @@ isdecltok(struct comp *cm) { struct token tk; if (peek(cm, &tk) == TKIDENT) { - struct decl *decl = finddecl(cm, tk.s); + struct decl *decl = finddecl(cm, tk.name); return decl && decl->scls == SCTYPEDEF; } else { static const char kws[] = { @@ -299,7 +299,7 @@ putdecl(struct comp *cm, const struct decl *decl) } static struct decl * -finddecl(struct comp *cm, const char *name) +finddecl(struct comp *cm, internstr name) { assert(name); for (struct env *e = cm->env; e; e = e->up) { @@ -315,7 +315,7 @@ finddecl(struct comp *cm, const char *name) } static union type -gettagged(struct comp *cm, struct span *span, enum typetag tt, const char *name, bool dodef) +gettagged(struct comp *cm, struct span *span, enum typetag tt, internstr name, bool dodef) { struct typedata td = {0}; assert(name); @@ -338,7 +338,7 @@ Break2: } static union type -deftagged(struct comp *cm, struct span *span, enum typetag tt, const char *name, union type ty) +deftagged(struct comp *cm, struct span *span, enum typetag tt, internstr name, union type ty) { struct typedata td = {0}; assert(name); @@ -703,7 +703,7 @@ callexpr(struct comp *cm, const struct span *span_, const struct expr *callee) } if (callee->t == ESYM && ty.t == IMPLICITFUNCTY) { /* implicit function decl.. */ - const char *name = (void *)callee->sym; + internstr name = (void *)callee->sym; struct decl decl = { (ty = mkfntype(mktype(TYINT), 0, NULL, /* kandr */ 1, 0)), .scls = SCEXTERN, .span = span, .name = name, .sym = name @@ -841,8 +841,8 @@ ppostfixopers(struct comp *cm, struct expr *ex) ex->ty.t == TYPTR && isagg(typechild(ex->ty)) ? "; did you mean to use '->'?" : ""); } else { struct fielddata fld = {.t = mktype(TYINT)}; - if (*tk2.s && !getfield(&fld, ex->ty, tk2.s)) - error(&span, "'%ty' has no such field: '%s'", ex->ty, tk2.s); + if (*tk2.s && !getfield(&fld, ex->ty, tk2.name)) + error(&span, "'%ty' has no such field: '%s'", ex->ty, tk2.name); if (ex->t == EGETF && ex->qual == fld.qual) { /* accumulate */ ex->span = span; ex->ty = fld.t; @@ -897,7 +897,7 @@ tkprec(int tt) } static struct expr initializer(struct comp *cm, union type *ty, enum evalmode ev, - bool globl, enum qualifier qual, const char *name); + bool globl, enum qualifier qual, internstr name); /* parse an expression with the given operator precedence */ /* param ident is a kludge to support block labels without backtracking or extra lookahead @@ -1000,10 +1000,10 @@ Unary: break; case TKIDENT: Ident: - decl = finddecl(cm, tk.s); + decl = finddecl(cm, tk.name); if (!decl) { if (peek(cm, NULL) == '(') { /* implicit function decl? */ - ex = mkexpr(ESYM, tk.span, mktype(IMPLICITFUNCTY), .sym = (void *)tk.s); + ex = mkexpr(ESYM, tk.span, mktype(IMPLICITFUNCTY), .sym = (void *)tk.name); } else { error(&tk.span, "undeclared identifier %'tk", &tk); ex = mkexpr(ESYM, tk.span, mktype(TYINT), .sym = NULL); @@ -1256,7 +1256,7 @@ struct initparser { vec_of(uchar) ddat; struct dreloc { struct dreloc *link; - const char *sym; + internstr sym; vlong addend; uint off; } *drel; @@ -1566,7 +1566,7 @@ Retry: } static int -aggdesignator(struct initparser *ip, union type ty, const char *name, const struct span *span) +aggdesignator(struct initparser *ip, union type ty, internstr name, const struct span *span) { const struct typedata *td = &typedata[ty.dat]; for (int i = 0; i < td->nmemb; ++i) { @@ -1645,15 +1645,14 @@ designators(struct initparser *ip, struct comp *cm) error(&span, "member designator used with non-aggregate type '%ty'", ip->sub->ty); else if (tk.t == TKIDENT) { int idx; - //if (!strcmp(tk.s, "_vb")) __asm__("int3;nop"); for (;;) { - idx = aggdesignator(ip, ip->sub->ty, tk.s, &span); + idx = aggdesignator(ip, ip->sub->ty, tk.name, &span); if (idx >= 0 || ip->sub == ip->cur) break; --ip->sub; } ip->sub->idx = idx; if (idx < 0) - error(&span, "%ty has no such field: '%s'", ip->cur->ty, tk.s); + error(&span, "%ty has no such field: '%s'", ip->cur->ty, tk.name); dumpini(ip); } some = 1; @@ -1668,7 +1667,7 @@ designators(struct initparser *ip, struct comp *cm) static struct expr initializer(struct comp *cm, union type *ty, enum evalmode ev, bool globl, - enum qualifier qual, const char *sym) + enum qualifier qual, internstr sym) { struct token tk; struct span span; @@ -1811,7 +1810,7 @@ initializer(struct comp *cm, union type *ty, enum evalmode ev, bool globl, /*****************/ static union type -buildagg(struct comp *cm, enum typetag tt, const char *name, int id) +buildagg(struct comp *cm, enum typetag tt, internstr name, int id) { struct token tk; union type t; @@ -1850,7 +1849,7 @@ buildagg(struct comp *cm, enum typetag tt, const char *name, int id) bitsiz = 0; if (st.bitf) { struct expr ex = constantexpr(cm); - const char *name = decl.name ? decl.name : "<anonymous>"; + const char *name = decl.name ? &decl.name->c : "<anonymous>"; if (!isint(decl.ty)) { error(&decl.span, "bit-field '%s' has non-integer type '%ty'", name, decl.ty); } else if (!isint(ex.ty)) { @@ -1931,7 +1930,7 @@ buildagg(struct comp *cm, enum typetag tt, const char *name, int id) if (td.flexi && ccopt.cstd < STDC99 && ccopt.pedant) warn(&flexspan, "flexible array member in %M is an extension"); if (fld.n == 0) { - struct namedfield dummy = { "", { mktype(TYCHAR), 0 }}; + struct namedfield dummy = { intern(""), { mktype(TYCHAR), 0 }}; error(&tk.span, "%s cannot have zero members", tag); vpush(&fld, dummy); td.siz = td.align = 1; @@ -1965,7 +1964,7 @@ inttyminmax(vlong *min, uvlong *max, enum typetag tt) * prefers to use unsigned types when possible). should add support for -fshort-enums */ static union type -buildenum(struct comp *cm, const char *name, const struct span *span, int id) +buildenum(struct comp *cm, internstr name, const struct span *span, int id) { struct token tk; vlong tymin, minv = 0; @@ -2003,7 +2002,7 @@ buildenum(struct comp *cm, const char *name, const struct span *span, int id) else if (issigned(ty) && iota < minv) minv = iota; - decl.name = tk.s; + decl.name = tk.name; decl.ty = ty; decl.isenum = 1; decl.value = iota++; @@ -2045,11 +2044,11 @@ tagtype(struct comp *cm, enum toktag kind) union type t; struct span span; enum typetag tt = kind == TKWenum ? TYENUM : kind == TKWstruct ? TYSTRUCT : TYUNION; - const char *tag = NULL; + internstr tag = NULL; peek(cm, &tk); if (match(cm, &tk, TKIDENT)) - tag = tk.s; + tag = tk.name; span = tk.span; if (!match(cm, NULL, '{')) { if (!tag) { @@ -2224,7 +2223,7 @@ declspec(struct declstate *st, struct comp *cm, struct span *pspan) st->base = ty; continue; case TKIDENT: - if (!st->base.t && !arith && (decl = finddecl(cm, tk.s)) + if (!st->base.t && !arith && (decl = finddecl(cm, tk.name)) && decl->scls == SCTYPEDEF) { lex(cm, &tk); st->base = decl->ty; @@ -2315,7 +2314,7 @@ static struct decllist { uint len; /* TYARRAY */ struct { /* TYFUNC */ union type *param; - const char **pnames; + internstr *pnames; struct span *pspans; uchar *pqual; short npar; @@ -2326,7 +2325,7 @@ static struct decllist { } decltmp[64], *declfreelist; static bool usingdeclparamtmp; static union type declparamtmp[16]; -static const char *declpnamestmp[16]; +static internstr declpnamestmp[16]; static struct span declpspanstmp[16]; static uchar declpqualtmp[16]; @@ -2354,7 +2353,7 @@ cvqual(struct comp *cm) } static void -decltypes(struct comp *cm, struct decllist *list, const char **name, struct span *span, struct span *namespan) +decltypes(struct comp *cm, struct decllist *list, internstr *name, struct span *span, struct span *namespan) { struct token tk; struct decllist *ptr, node; @@ -2395,7 +2394,7 @@ decltypes(struct comp *cm, struct decllist *list, const char **name, struct span if (!name) error(&tk.span, "unexpected identifier in type name"); else { - *name = tk.s; + *name = tk.name; *namespan = tk.span; } lex(cm, &tk); @@ -2444,7 +2443,7 @@ decltypes(struct comp *cm, struct decllist *list, const char **name, struct span } else if (match(cm, &tk, '(')) Func: { vec_of(union type) params = {0}; vec_of(uchar) qual = {0}; - vec_of(const char *) names = {0}; + vec_of(internstr) names = {0}; vec_of(struct span) spans = {0}; if (!usingdeclparamtmp) { @@ -2471,7 +2470,7 @@ decltypes(struct comp *cm, struct decllist *list, const char **name, struct span if (node.kandr) { if (match(cm, &tk, TKIDENT)) { vpush(¶ms, mktype(TYINT)); - vpush(&names, tk.s); + vpush(&names, tk.name); vpush(&spans, tk.span); } else error(&tk.span, "expected identifier"); } else if (!isdecltok(cm) && peek(cm, &tk) != TKIDENT) { @@ -2720,7 +2719,7 @@ structreturn(struct function *fn, const struct expr *src) static union ref compilecall(struct function *fn, const struct expr *ex); -static const char * +static internstr mkhiddensym(const char *fnname, const char *name, int id) { char buf[200]; @@ -2738,7 +2737,7 @@ mkhiddensym(const char *fnname, const char *name, int id) static void geninit(struct function *fn, union type t, union ref dst, const struct expr *src); static union ref condexprvalue(struct function *fn, const struct expr *ex, bool discard); -static const char *istr__func__; +static internstr istr__func__, istr_main, istr_memset; union ref expraddr(struct function *fn, const struct expr *ex) @@ -2757,7 +2756,7 @@ expraddr(struct function *fn, const struct expr *ex) case SCEXTERN: case SCNONE: case SCSTATIC: if (!decl->sym) { /* lazy __func__ */ assert(decl->name == istr__func__); - decl->sym = mkhiddensym(fn->name, "__func__", 1); + decl->sym = mkhiddensym(&fn->name->c, &intern("__func__")->c, 1); uint off = objnewdat(decl->sym, objout.code ? Stext : Srodata, 0, typesize(decl->ty), typealign(decl->ty)); uchar *p = objout.code ? objout.textbegin + off : objout.rodata.p + off; memcpy(p, fn->name, typearrlen(decl->ty)-1); @@ -2798,7 +2797,7 @@ expraddr(struct function *fn, const struct expr *ex) static int id; struct initparser ip[1] = {0}; union type ty = ex->ty; - const char *sym = mkhiddensym(NULL, ".LC", ++id); + internstr sym = mkhiddensym(NULL, ".LC", ++id); ip->sec = Sdata; /* TODO put in rodata if possible */ ip->ev = EVSTATICINI; assert(!isincomplete(ty)); @@ -2895,7 +2894,7 @@ geninit(struct function *fn, union type t, union ref dst, const struct expr *src addinstr(fn, mkarginstr(cls2type(KPTR), dst)); addinstr(fn, mkarginstr(cls2type(KI32), ZEROREF)); addinstr(fn, mkarginstr(cls2type(type2cls[targ_sizetype]), mkintcon(type2cls[targ_sizetype], siz))); - call.l = mksymref("memset", 1); + call.l = mksymref(istr_memset, 1); call.r = mkcallarg(cls2type(KPTR), 3, -1); addinstr(fn, call); } @@ -3622,7 +3621,7 @@ static void localdecl(struct comp *cm, struct function *fn, bool forinit); struct label { struct label *link; - const char *name; + internstr name; struct block *blk; struct span usespan; /* if usespan.ex.len == 0, this label is resolved and blk is the block that @@ -3632,7 +3631,7 @@ struct label { }; static struct label * -findlabel(struct comp *cm, const char *name) +findlabel(struct comp *cm, internstr name) { for (struct label *l = cm->labels; l; l = l->link) if (l->name == name) return l; @@ -3640,7 +3639,7 @@ findlabel(struct comp *cm, const char *name) } static void -deflabel(struct comp *cm, struct function *fn, const struct span *span, const char *name) +deflabel(struct comp *cm, struct function *fn, const struct span *span, internstr name) { struct label *label = findlabel(cm, name); if (label && label->usespan.ex.len == 0) { @@ -3845,7 +3844,7 @@ stmt(struct comp *cm, struct function *fn) } } else if (tk.t == TKIDENT && match(cm, NULL, ':')) { /* <label> ':' */ - deflabel(cm, fn, &tk.span, tk.s); + deflabel(cm, fn, &tk.span, tk.name); } else { assert(tk.t == TKIDENT); /* kludge for no backtracking and no lookahead */ @@ -4083,10 +4082,10 @@ stmt(struct comp *cm, struct function *fn) lex(cm, &tk); peek(cm, &tk); if (expect(cm, TKIDENT, NULL)) { - struct label *label = findlabel(cm, tk.s); + struct label *label = findlabel(cm, tk.name); if (!label) { /* create reloc list */ - struct label l = { cm->labels, tk.s, fn->curblk, tk.span }; + struct label l = { cm->labels, tk.name, fn->curblk, tk.span }; assert(l.usespan.ex.len); cm->labels = alloccopy(fn->arena, &l, sizeof l, 0); fn->curblk = NULL; @@ -4151,12 +4150,12 @@ localdecl(struct comp *cm, struct function *fn, bool forini) if (!forini && match(cm, &tk, TKIDENT)) { if (match(cm, NULL, ':')) { /* <label> ':' */ - deflabel(cm, fn, &tk.span, tk.s); + deflabel(cm, fn, &tk.span, tk.name); stmt(cm, fn); return; } /* finddecl() -> non null because localdecl() is called when isdecltok() */ - st.base = finddecl(cm, tk.s)->ty; + st.base = finddecl(cm, tk.name)->ty; st.base0 = 1; } do { @@ -4171,7 +4170,7 @@ localdecl(struct comp *cm, struct function *fn, bool forini) case SCSTATIC: if (forini) error(&decl.span, "static declaration in 'for' loop initializer"); - decl.sym = mkhiddensym(fn->name, decl.name, ++staticid); + decl.sym = mkhiddensym(&fn->name->c, &decl.name->c, ++staticid); goto Initz; case SCNONE: if (decl.ty.t == TYFUNC) { @@ -4274,7 +4273,7 @@ block(struct comp *cm, struct function *fn) } static void -function(struct comp *cm, struct function *fn, const char **pnames, const struct span *pspans, uchar *pquals) +function(struct comp *cm, struct function *fn, internstr *pnames, const struct span *pspans, uchar *pquals) { const struct typedata *td = &typedata[fn->fnty.dat]; const bool doemit = fn->curblk; @@ -4312,7 +4311,7 @@ function(struct comp *cm, struct function *fn, const char **pnames, const struct /* put __func__, though its data is generated lazily in expraddr() */ putdecl(cm, &(struct decl) { - .ty = mkarrtype(mktype(TYCHAR), QCONST, strlen(fn->name) + 1), .qual = QCONST, + .ty = mkarrtype(mktype(TYCHAR), QCONST, strlen(&fn->name->c) + 1), .qual = QCONST, .name = istr__func__, .scls = SCSTATIC, .span = (peek(cm, &tk), tk.span), }); @@ -4331,7 +4330,7 @@ function(struct comp *cm, struct function *fn, const char **pnames, const struct } } if (fn->curblk) { - if (!strcmp(fn->name, "main") && fn->retty.t == TYINT) { + if (fn->retty.t == TYINT && fn->name == istr_main) { /* implicit return 0 for main function (ISO C standard behavior) */ putreturn(fn, ZEROREF, NOREF); } else { @@ -4355,6 +4354,8 @@ docomp(struct comp *cm) struct token tk[1]; istr__func__ = intern("__func__"); + istr_main = intern("main"); + istr_memset = intern("memset"); if (!cm->env) { vinit(&envdecls, NULL, 1<<10); pmap_init(&tldeclmap, 1<<8); @@ -4363,7 +4364,7 @@ docomp(struct comp *cm) if (!cvalistty.t) { struct typedata td = { .t = TYSTRUCT, .siz = targ_valistsize, .align = targ_primalign[TYPTR], .nmemb = 1, - .fld = &(struct namedfield){"-", {mkarrtype(mktype(TYPTR), 0, 3)}} + .fld = &(struct namedfield){intern("-"), {mkarrtype(mktype(TYPTR), 0, 3)}} }; cvalistty = mkarrtype(mktagtype(intern("__builtin_va_list"), &td), 0, 1); } @@ -92,9 +92,9 @@ struct decl { isdef : 1, isbuiltin : 1; struct span span; - const char *name; + internstr name; union { - const char *sym; + internstr sym; struct { ushort align; int id; }; vlong value; const struct builtin *builtin; @@ -26,7 +26,7 @@ identkeyword(struct token *tk, const char *s, int len) } tk->blue = 0; tk->len = len; - struct kw *kw = pmap_get(&kwmap, tk->s = intern(s)); + struct kw *kw = pmap_get(&kwmap, tk->name = intern(s)); if (kw) { tk->t = kw->t; tk->extwarn = kw->ext; @@ -580,7 +580,7 @@ End: /****************/ struct macro { - const char **param; + internstr *param; struct span0 span; uchar nparam; bool predef : 1, @@ -608,7 +608,7 @@ tokequ(const struct token *a, const struct token *b) if (a->len != b->len) return 0; return !memcmp(a->s, b->s, a->len); } else if (a->t == TKIDENT) { - return a->s == b->s; + return a->name == b->name; } else if (a->t == TKPPMACARG || a->t == TKPPMACSTR) { return a->argidx == b->argidx; } @@ -656,7 +656,7 @@ freemac(struct macro *mac) static pmap_of(struct macro) macroht; static void -putmac(const char *name, struct macro *mac) +putmac(internstr name, struct macro *mac) { static short id; if (!macroht.v) pmap_init(¯oht, 1<<10); @@ -681,7 +681,7 @@ putmac(const char *name, struct macro *mac) } static void -delmac(const char *name) +delmac(internstr name) { struct macro *slot = pmap_get(¯oht, name); if (!slot) return; @@ -690,7 +690,7 @@ delmac(const char *name) } static struct macro * -findmac(const char *name) +findmac(internstr name) { return pmap_get(¯oht, name); } @@ -759,7 +759,7 @@ static void ppdefine(struct lexer *lx) { struct token tk0, tk; - const char *mname; + internstr mname; struct macro mac = {0}; vec_of(struct token) rlist = {0}; @@ -769,12 +769,12 @@ ppdefine(struct lexer *lx) ppskipline(lx); return; } - mname = tk0.s; + mname = tk0.name; mac.span = tk0.span.sl; if (match(lx, '(')) { /* gather params for function-like macro */ - vec_of(const char *) params = {0}; + vec_of(internstr) params = {0}; vinit(¶ms, NULL, 4); mac.fnlike = 1; while (lex0(lx, &tk) != ')') { @@ -791,7 +791,7 @@ ppdefine(struct lexer *lx) lex0(lx, &tk); } if (isppident(tk)) - vpush(¶ms, tk.s); + vpush(¶ms, tk.name); else if (tk.t == TKDOTS) { mac.variadic = 1; vpush(¶ms, intern("__VA_ARGS__")); @@ -812,7 +812,7 @@ ppdefine(struct lexer *lx) warn(&tk.span, "no whitespace after macro name"); if (mac.fnlike && isppident(tk)) { for (int i = 0; i < mac.nparam; ++i) { - if (tk.s == mac.param[i]) { + if (tk.name == mac.param[i]) { tk.argidx = i; if (rlist.n > 0 && rlist.p[rlist.n - 1].t == '#') { tk.t = TKPPMACSTR; @@ -868,7 +868,7 @@ ppundef(struct lexer *lx) return; } expecteol(lx, "undef"); - delmac(tk.s); + delmac(tk.name); } static struct macrostack { @@ -906,14 +906,14 @@ popmac(struct lexer *lx) } while ((stk = lx->macstk) && stk->idx >= stk->rlist.n && !stk->stop); } -static void expandfnmacro(struct lexer *lx, struct span *span, const char *mname, struct macro *mac); +static void expandfnmacro(struct lexer *lx, struct span *span, internstr mname, struct macro *mac); static bool tryexpand(struct lexer *lx, struct token *tk) { struct span span = tk->span; struct macro *mac = NULL; - const char *mname = tk->s; + internstr mname = tk->name; if (!isppident(*tk) || !(mac = findmac(mname)) || tk->blue) return 0; @@ -962,7 +962,7 @@ tryexpand(struct lexer *lx, struct token *tk) } static void -expandfnmacro(struct lexer *lx, struct span *span, const char *mname, struct macro *mac) +expandfnmacro(struct lexer *lx, struct span *span, internstr mname, struct macro *mac) { vec_of(struct token) argsbuf = {0}, /* argument tokens pre-expansion */ rlist2 = {0}; /* macro replacement list with arguments subsituted */ @@ -1266,7 +1266,7 @@ Unary: error(&tk.span, "expected `)'"); goto Err; } - x = findmac(tk.s) != NULL; + x = findmac(tk.name) != NULL; } else { if (tryexpand(lx, &tk)) goto Unary; @@ -1397,11 +1397,11 @@ ppifxdef(struct lexer *lx, bool defp, const struct span *span) return; } expecteol(lx, defp ? "ifdef" : "ifndef"); - if (!defp && lx->firstdirective) lx->inclguard = tk.s; + if (!defp && lx->firstdirective) lx->inclguard = tk.name; assert(nppcnd < countof(ppcndstk) && "too many nested #if"); ppcndstk[nppcnd].ifspan = span->sl; ppcndstk[nppcnd].filedepth = includedepth; - ppcndstk[nppcnd].cnd = (findmac(tk.s) == NULL) ^ defp ? PPCNDTRUE : PPCNDFALSE; + ppcndstk[nppcnd].cnd = (findmac(tk.name) == NULL) ^ defp ? PPCNDTRUE : PPCNDFALSE; ppcndstk[nppcnd++].elsep = 0; } @@ -1452,7 +1452,7 @@ ppelifxdef(struct lexer *lx, bool defp, const struct span *span) expecteol(lx, defp ? "elifdef" : "elifndef"); switch (cnd->cnd) { case PPCNDTRUE: cnd->cnd = PPCNDTAKEN; break; - case PPCNDFALSE: cnd->cnd = (findmac(tk.s) == NULL) ^ defp ? PPCNDTRUE : PPCNDFALSE; break; + case PPCNDFALSE: cnd->cnd = (findmac(tk.name) == NULL) ^ defp ? PPCNDTRUE : PPCNDFALSE; break; case PPCNDTAKEN: assert(0); } } @@ -1975,8 +1975,7 @@ addpredefmacros(struct arena **tmparena) } tok_ver.len = 7; for (int i = 0; i < countof(macs); ++i) { - macs[i].name = intern(macs[i].name); - putmac(macs[i].name, &macs[i].m); + putmac(intern(macs[i].name), &macs[i].m); } switch (targ_mcisa) { @@ -2015,7 +2014,7 @@ initlexer(struct lexer *lx, const char **err, const char *file) int fileid = openfile(err, &f, file); if (fileid < 0) return LXERR; - const char *guard; + internstr guard; if (isfileseen(fileid) && isoncefile(fileid, &guard) && (!guard || findmac(guard))) { //efmt("skipping %s .. guard %s\n", file, guard ? guard : "<none>"); return LXFILESKIP; @@ -62,6 +62,7 @@ struct token { }; struct span span; union { + internstr name; const char *s; const ushort *ws16; const uint *ws32; @@ -101,7 +102,7 @@ struct lexer { struct arena **tmparena; bool firstdirective; ushort nppcnd0; - const char *inclguard; + internstr inclguard; }; enum initlexer { @@ -179,7 +179,8 @@ void free(void *); #define xrealloc(p,n) xrealloc(p, n, __func__) /* string interning */ -const char *intern(const char *); +typedef const struct internstr {char c;} *internstr; +internstr intern(const char *); /* growable buffer that stores its capacity in the allocated memory */ #define xbnew_(n) (void *)(1 + (size_t *)xcalloc(sizeof(size_t) + (n))) @@ -404,8 +405,8 @@ struct memfile *getfile(int id); void addfileline(int id, uint off); void setfileline(int id, uint off, int line, const char *file); const char *getfilepos(int *line, int *col, int id, uint off); -bool isoncefile(int id, const char **guard); -void markfileonce(int id, const char *guard); +bool isoncefile(int id, internstr *guard); +void markfileonce(int id, internstr guard); void markfileseen(int id); bool isfileseen(int id); void closefile(int id); @@ -226,7 +226,7 @@ pritypebefore(struct wbuf *buf, union type ty, int qual) case TYSTRUCT: s = "struct"; Tagged: - n = bfmt(buf, "%s %s", s, (s2 = ttypenames[typedata[ty.dat].id]) ? s2 : "(anonymous)"); + n = bfmt(buf, "%s %s", s, (s2 = &ttypenames[typedata[ty.dat].id]->c) ? s2 : "(anonymous)"); return n + priquals(buf, qual); case TYUNION: s = "union"; @@ -530,7 +530,7 @@ vbfmt(struct wbuf *out, const char *fmt, va_list ap) case TKPPMACARG: case TKIDENT: if (quote) n += bputc(buf, '`'); - n += bfmt(buf, "%s", tok->s); + n += bfmt(buf, "%s", tok->name); if (quote) n += bputc(buf, '\''); break; case TKEOF: @@ -562,7 +562,7 @@ vbfmt(struct wbuf *out, const char *fmt, va_list ap) default: if (quote) n += bputc(buf, '`'); if (in_range(tok->t, TKWBEGIN_, TKWEND_)) { - iowrite(buf, tok->s, tok->len); + iowrite(buf, tok->name, tok->len); n += tok->len; } else if (aisprint(tok->t)) { n += bputc(buf, tok->t); @@ -809,7 +809,7 @@ static struct file { vec_of(struct linemap) linemap; bool once; bool seen; - const char *guardmac; + internstr guardmac; } *fileht[1<<SPANFILEBITS]; static int nfiles; @@ -971,7 +971,7 @@ getfilepos(int *pline, int *pcol, int id, uint off) } bool -isoncefile(int id, const char **guard) +isoncefile(int id, internstr *guard) { assert(id < countof(fileht) && fileht[id]); *guard = fileht[id]->guardmac; @@ -979,7 +979,7 @@ isoncefile(int id, const char **guard) } void -markfileonce(int id, const char *guard) +markfileonce(int id, internstr guard) { assert(id < countof(fileht) && fileht[id]); fileht[id]->once = 1; diff --git a/ir/intrin.c b/ir/intrin.c index 2ef826c..53e29fc 100644 --- a/ir/intrin.c +++ b/ir/intrin.c @@ -24,7 +24,7 @@ intrin(struct block *blk, int *curi, enum intrin in, struct arg *args, int narg, /* memcpy */ *args[1].ty = *args[0].ty = mktyperef(cls2type(KPTR)); insertinstr(blk, (*curi)++, mkarginstr(cls2type(cls), mkintcon(cls, td->siz))); - *this = mkinstr(Ocall, 0, mksymref("memcpy", 1), this->r); + *this = mkinstr(Ocall, 0, mksymref(intern("memcpy"), 1), this->r); calltab.p[this->r.i].narg = 3; calltab.p[this->r.i].ret = cls2type(0); return 0; @@ -138,14 +138,14 @@ mkfltcon(enum irclass k, double f) } union ref -mksymref(const char *s, bool isfunc) +mksymref(internstr s, bool isfunc) { struct xcon con = { .issym = 1, .sym = s, .isfunc = isfunc }; return mkref(RXCON, addcon(&con)); } union ref -mkdatref(const char *name, union type ctype, uint siz, uint align, const void *bytes, uint n, bool deref) +mkdatref(internstr name, union type ctype, uint siz, uint align, const void *bytes, uint n, bool deref) { struct irdat dat = { .ctype = ctype, .align = align, .siz = siz, .name = name }; dat.section = objout.code && align >= 4 && align <= targ_primsizes[TYPTR] && siz <= 16 ? Stext : Srodata; @@ -168,7 +168,7 @@ mkdatref(const char *name, union type ctype, uint siz, uint align, const void *b return mkref(RXCON, addcon(&(struct xcon){.isdat = 1, .deref = deref, .dat = dattab.n - 1})); } -const char * +internstr xcon2sym(int ref) { struct xcon con = conht[ref]; @@ -22,14 +22,14 @@ struct irdat { union type ctype; uint siz; uint off; - const char *name; + internstr name; }; struct xcon { bool issym, isdat, isfunc, deref; uchar cls; union { - const char *sym; + internstr sym; int dat; vlong i; double f; @@ -163,7 +163,7 @@ enum { }; struct function { struct arena **arena; - const char *name; + internstr name; struct block *entry, *curblk; struct use *use; short *nuse; @@ -250,9 +250,9 @@ union ref mkfltcon(enum irclass, double); #define isaddrcon(r,derefok) ((r).t == RXCON && !conht[(r).i].cls && (derefok || !conht[(r).i].deref)) #define intconval(r) ((r).t == RICON ? (r).i : conht[(r).i].i) #define fltconval(r) ((r).t == RICON ? (r).i : conht[(r).i].f) -union ref mksymref(const char *, bool isfunc); -union ref mkdatref(const char *name, union type ctype, uint siz, uint align, const void *, uint n, bool deref); -const char *xcon2sym(int ref); +union ref mksymref(internstr, bool isfunc); +union ref mkdatref(internstr name, union type ctype, uint siz, uint align, const void *, uint n, bool deref); +internstr xcon2sym(int ref); struct instr mkalloca(uint siz, uint align); union ref mkcallarg(union irtype ret, uint narg, int vararg); #define mkintrin(B, C, N) mkinstr(Ointrin, C, {{.t=RICON,B}}, mkcallarg((union irtype){{0}},N,-1)) @@ -37,12 +37,12 @@ void * } /** string interning **/ -const char * +internstr intern(const char *s) { static uint N, n; static struct ht { - const char *s; + internstr s; size_t h; } *ht; static struct { char m[sizeof(struct arena) + (2<<10)]; struct arena *_a; } amem; @@ -75,7 +75,7 @@ intern(const char *s) N = nnew; i = h; continue; - } else if (h == ht[i].h && !strcmp(s, ht[i].s)) { + } else if (h == ht[i].h && !strcmp(s, &ht[i].s->c)) { return ht[i].s; } ++i; @@ -29,7 +29,7 @@ struct reloc { vlong addend; union { uint symidx; - const char *symname; + internstr symname; }; }; static vec_of(struct reloc) relocs; @@ -78,7 +78,7 @@ str2idx(const char *s) } static struct sym * -findsym(const char *s) +findsym(internstr s) { ushort *idx = pmap_get(&symht, s); return idx ? &symtab.p[*idx] : NULL; @@ -102,7 +102,7 @@ static const char sect2ndx[] = { }; enum section -elfhassym(const char *nam, uint *value) +elfhassym(internstr nam, uint *value) { struct sym *sym = findsym(nam); if (sym) { @@ -113,12 +113,12 @@ elfhassym(const char *nam, uint *value) } void -elfaddsym(const char *nam, int info, enum section sect, uvlong value, uvlong size) +elfaddsym(internstr nam, int info, enum section sect, uvlong value, uvlong size) { struct sym *sym = findsym(nam), sym0; if (!sym) { sym = &sym0; - sym->name = str2idx(nam); + sym->name = str2idx(&nam->c); } sym->bind = info >> 4; sym->type = info & 0xF; @@ -145,7 +145,7 @@ static const ushort relktab[][NRELOCKIND] = { }; void -elfreloc(const char *sym, enum relockind kind, enum section section, uint off, vlong addend) +elfreloc(internstr sym, enum relockind kind, enum section section, uint off, vlong addend) { switch (section) { default: assert(0); @@ -401,7 +401,7 @@ elffini(struct wbuf *out) rel->symidx = idx < ndefsym ? defsym2idx[idx] : idx; } else { assert(symtab.n < 1<<16); - vpush(&symtab, ((struct sym) { str2idx(rel->symname), .bind = STB_GLOBAL, .type = STT_NOTYPE, .shndx = SHN_UND })); + vpush(&symtab, ((struct sym) { str2idx(&rel->symname->c), .bind = STB_GLOBAL, .type = STT_NOTYPE, .shndx = SHN_UND })); pmap_set(&symht, rel->symname, symtab.n-1); rel->symidx = symtab.n-1; } @@ -6,9 +6,9 @@ void elfinit(void); -enum section elfhassym(const char *, uint *value); -void elfaddsym(const char *, int info, enum section, uvlong value, uvlong size); -void elfreloc(const char *sym, enum relockind, enum section, uint off, vlong addend); +enum section elfhassym(internstr , uint *value); +void elfaddsym(internstr , int info, enum section, uvlong value, uvlong size); +void elfreloc(internstr sym, enum relockind, enum section, uint off, vlong addend); void elffini(struct wbuf *); struct objfile objout; @@ -30,7 +30,7 @@ objini(const char *infile, const char *outfile) } void -objdeffunc(const char *nam, bool globl, uint off, uint siz) +objdeffunc(internstr nam, bool globl, uint off, uint siz) { switch (mctarg->objkind) { case OBJELF: @@ -40,13 +40,13 @@ objdeffunc(const char *nam, bool globl, uint off, uint siz) } enum section -objhassym(const char *name, uint *off) +objhassym(internstr name, uint *off) { return elfhassym(name, off); } uint -objnewdat(const char *name, enum section sec, bool globl, uint siz, uint align) +objnewdat(internstr name, enum section sec, bool globl, uint siz, uint align) { struct objfile *o = &objout; uint off; @@ -90,7 +90,7 @@ objnewdat(const char *name, enum section sec, bool globl, uint siz, uint align) } void -objreloc(const char *sym, enum relockind reloc, enum section section, uint off, vlong addend) +objreloc(internstr sym, enum relockind reloc, enum section section, uint off, vlong addend) { switch (mctarg->objkind) { case OBJELF: @@ -22,10 +22,10 @@ enum relockind { enum section { Snone, Stext, Srodata, Sdata, Sbss }; void objini(const char *infile, const char *outfile); -void objdeffunc(const char *nam, bool globl, uint off, uint siz); -enum section objhassym(const char *name, uint *off); -uint objnewdat(const char *name, enum section, bool globl, uint siz, uint align); -void objreloc(const char *sym, enum relockind, enum section, uint off, vlong addend); +void objdeffunc(internstr nam, bool globl, uint off, uint siz); +enum section objhassym(internstr name, uint *off); +uint objnewdat(internstr name, enum section, bool globl, uint siz, uint align); +void objreloc(internstr sym, enum relockind, enum section, uint off, vlong addend); void objfini(void); /* vim:set ts=3 sw=3 expandtab: */ @@ -1,7 +1,7 @@ #include "type.h" struct typedata typedata[1<<13]; -const char *ttypenames[1<<10]; +internstr ttypenames[1<<10]; static ushort hashtd(const struct typedata *td) @@ -183,7 +183,7 @@ mkfntype(union type ret, uint n, const union type *par, bool kandr, bool variadi } union type -completetype(const char *name, int id, struct typedata *td) +completetype(internstr name, int id, struct typedata *td) { assert(td->t == TYENUM || td->t == TYSTRUCT || td->t == TYUNION); td->id = id; @@ -196,14 +196,14 @@ completetype(const char *name, int id, struct typedata *td) } union type -mktagtype(const char *name, struct typedata *td) +mktagtype(internstr name, struct typedata *td) { static int id; return completetype(name, id++, td); } static bool -getfieldrec(struct fielddata *res, uint off, const struct typedata *td, const char *name) +getfieldrec(struct fielddata *res, uint off, const struct typedata *td, internstr name) { Begin: for (int i = 0; i < td->nmemb; ++i) { @@ -227,7 +227,7 @@ Begin: } bool -getfield(struct fielddata *res, union type ty, const char *name) +getfield(struct fielddata *res, union type ty, internstr name) { assert(isagg(ty)); return getfieldrec(res, 0, &typedata[ty.dat], name); @@ -66,7 +66,7 @@ union type { #define mktype(...) ((union type) {{ __VA_ARGS__ }}) struct enumvar { - const char *name; + internstr name; union { vlong i; uvlong u; }; }; @@ -78,7 +78,7 @@ struct fielddata { qual : 2; }; struct namedfield { - const char *name; + internstr name; struct fielddata f; }; @@ -118,7 +118,7 @@ struct typedata { }; extern struct typedata typedata[]; -extern const char *ttypenames[/*id*/]; +extern internstr ttypenames[/*id*/]; bool isincomplete(union type); uint typesize(union type); @@ -126,9 +126,9 @@ uint typealign(union type); union type mkptrtype(union type, int qual); union type mkarrtype(union type t, int qual, uint n); union type mkfntype(union type ret, uint n, const union type *, bool kandr, bool variadic); -union type mktagtype(const char *name, struct typedata *td); -bool getfield(struct fielddata *res, union type, const char *); -union type completetype(const char *name, int id, struct typedata *td); +union type mktagtype(internstr name, struct typedata *td); +bool getfield(struct fielddata *res, union type, internstr); +union type completetype(internstr name, int id, struct typedata *td); union type typedecay(union type); bool assigncompat(union type dst, union type src); enum typetag intpromote(enum typetag); diff --git a/x86_64/emit.c b/x86_64/emit.c index 3c72712..8a1673d 100644 --- a/x86_64/emit.c +++ b/x86_64/emit.c @@ -251,7 +251,7 @@ opermatch(enum operpat pat, struct oper oper) static bool usebp; /* use RBP? */ static int rbpoff; -static const char *curfnsym; +static internstr curfnsym; static uchar *fnstart; /* Given an instruction description table, find the first entry that matches @@ -334,7 +334,7 @@ encode(uchar **pcode, const struct desc *tab, int ntab, enum irclass k, struct o static uchar offs[NOPERENC] = { [EN_MI8] = 1, [EN_MI16] = 2, [EN_MI32] = 4 }; uint addr; int disp = mem.disp - 4 - offs[en->operenc]; - const char *sym = xcon2sym(mem.con); + internstr sym = xcon2sym(mem.con); B(/*mod 0*/ (reg & 7) << 3 | RBP); if (objhassym(sym, &addr) == Stext) { I32(addr - (*pcode - objout.textbegin) + disp); @@ -433,7 +433,7 @@ encode(uchar **pcode, const struct desc *tab, int ntab, enum irclass k, struct o if (rex) B(0x40 | rex); D(opc, nopc); assert(dst.t == OSYM); - const char *sym = xcon2sym(dst.con); + internstr sym = xcon2sym(dst.con); uint addr; if (sym == curfnsym) { I32(fnstart - *pcode - 4); |