From 302e24671942051d70707586cf8c605a5815edac Mon Sep 17 00:00:00 2001 From: lemon Date: Mon, 15 Dec 2025 22:39:52 +0100 Subject: 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. --- ir/intrin.c | 2 +- ir/ir.c | 6 +++--- ir/ir.h | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'ir') 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; diff --git a/ir/ir.c b/ir/ir.c index d932121..883e728 100644 --- a/ir/ir.c +++ b/ir/ir.c @@ -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]; diff --git a/ir/ir.h b/ir/ir.h index 1a1d907..8c2990e 100644 --- a/ir/ir.h +++ b/ir/ir.h @@ -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)) -- cgit v1.2.3