diff options
Diffstat (limited to 'bootstrap')
| -rw-r--r-- | bootstrap/.gitignore | 1 | ||||
| -rw-r--r-- | bootstrap/all.h | 28 | ||||
| -rw-r--r-- | bootstrap/cgen.c | 79 | ||||
| -rw-r--r-- | bootstrap/dump.c | 9 | ||||
| -rw-r--r-- | bootstrap/env.c | 28 | ||||
| -rw-r--r-- | bootstrap/main.c | 1 | ||||
| -rw-r--r-- | bootstrap/parse.c | 178 | ||||
| -rw-r--r-- | bootstrap/test.cff | 40 | ||||
| -rw-r--r-- | bootstrap/types.c | 67 | ||||
| -rw-r--r-- | bootstrap/util.c | 17 |
10 files changed, 336 insertions, 112 deletions
diff --git a/bootstrap/.gitignore b/bootstrap/.gitignore index b5e3e58..51939a1 100644 --- a/bootstrap/.gitignore +++ b/bootstrap/.gitignore @@ -1,4 +1,5 @@ compile_commands.json a.out cff0 +.gdb_history .cache/ diff --git a/bootstrap/all.h b/bootstrap/all.h index 15f932c..ff20c25 100644 --- a/bootstrap/all.h +++ b/bootstrap/all.h @@ -177,6 +177,7 @@ struct type { const char *name; const struct type *ty; }) flds; + slice_t(struct decl) decls; bool fwd; int id; } agg; @@ -263,6 +264,7 @@ enum exprtype { Ezeroini, Eini, Eget, + Emcall, }; struct blockstmt { @@ -316,6 +318,10 @@ struct expr { struct expr *lhs; const char *fld; } get; + struct { + struct fn *met; + slice_t(struct expr) args; + } mcall; }; }; @@ -434,15 +440,27 @@ bswap64(u64 x) { #define vec_slice_cpy(slice, v) \ ((slice)->d = vec_compact(v), \ (slice)->n = (v)->length) + +#define container_of(x, T, fld) \ + (T *)((char *)(x) - offsetof(T, fld)) + /// ///////////////////////////////// /** util.c **/ -u32 jkhash(u32 hash, const u8 *data, size_t length); -#define jkhashv(h, v) jkhash(h, (void *)&(v), sizeof((v))) +#define FNV1A_INI 0x84222325u +u32 fnv1a(u32 hash, const void *data, size_t length); +static inline u32 +fnv1ai(u32 hash, int i) { + return fnv1a(hash, &i, sizeof i); +} +static inline u32 +fnv1aI(u32 hash, i64 i) { + return fnv1a(hash, &i, sizeof i); +} static inline u32 -jkhashu32(u32 h, u32 x) { - return jkhashv(h, x); +fnv1az(u32 hash, size_t i) { + return fnv1a(hash, &i, sizeof i); } int addfilepath(const char *); const char *fileid2path(int); @@ -485,7 +503,7 @@ const struct type *typeof2(const struct type *a, const struct type *b); /** env.c **/ struct decl *envfind(const struct env *, const char *name); -bool envput(struct env *, const struct decl *decl); +struct decl *envput(struct env *, const struct decl *decl); struct env *mkenv(const struct env *parent); /** dump.c **/ diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c index 8685ffe..3df1ce7 100644 --- a/bootstrap/cgen.c +++ b/bootstrap/cgen.c @@ -33,7 +33,7 @@ gentype(const struct type *ty) { case TYeunion: assert(ty->_cname); pri("%s", ty->_cname); - return; + break; case TYenum: gentype(ty->enu.intty); break; @@ -155,6 +155,8 @@ geniniex(struct expr *ex) { static void genexpr(struct expr *ex) { const struct type *ty = unconstify(ex->ty); + struct decl *decl; + switch (ex->t) { case Eintlit: intlit: @@ -234,6 +236,17 @@ genexpr(struct expr *ex) { case Eget: pri("%e%s%s", ex->get.lhs, ex->get.lhs->ty->t == TYptr ? "->" : ".", ex->get.fld); break; + case Emcall: + decl = container_of(ex->mcall.met, struct decl, fn); + assert(*decl->_cname); + pri("%s(", *decl->_cname); + for (int i = 0; i < ex->mcall.args.n; ++i) { + pri("%e", &ex->mcall.args.d[i]); + if (i < ex->mcall.args.n - 1) + pri(", "); + } + pri(")"); + break; } } @@ -343,7 +356,7 @@ genblock(struct blockstmt block) { static void liftnested(struct stmt *stmt); -// lift nested fns and static vars +static void liftdecl(struct decl *decl); static void liftnestedex(struct expr *ex) { @@ -390,12 +403,41 @@ liftnestedex(struct expr *ex) { case Eget: liftnestedex(ex->get.lhs); break; + case Emcall: + liftdecl(container_of(ex->mcall.met, struct decl, fn)); + for (int i = 0; i < ex->call.args.n; ++i) + liftnestedex(&ex->mcall.args.d[i]); + break; + } +} + +static void +liftdecl(struct decl *decl) { + static int id; + switch (decl->t) { + case Dfn: + if (decl->fn.body) { + *decl->_cname = xasprintf("__f%s_%d", decl->fn.name, id++); + genfn(decl->externp, *decl->_cname, &decl->fn); + } + break; + case Dstatic: + if (!decl->externp) { + assert(decl->var.ini); + *decl->_cname = xasprintf("__s%s_%d", decl->name, id++); + genstatic(decl->externp, *decl->_cname, &decl->var); + } + break; + case Dlet: + liftnestedex(decl->var.ini); + break; + default: + break; } } static void // lift nested fns and static vars liftnested(struct stmt *stmt) { - static int id; if (!stmt) return; switch (stmt->t) { @@ -407,26 +449,7 @@ liftnested(struct stmt *stmt) { liftnestedex(&stmt->expr); break; case Sdecl: - switch (stmt->decl.t) { - case Dfn: - if (stmt->decl.fn.body) { - *stmt->decl._cname = xasprintf("__f%s_%d", stmt->decl.fn.name, id++); - genfn(stmt->decl.externp, *stmt->decl._cname, &stmt->decl.fn); - } - break; - case Dstatic: - if (!stmt->decl.externp) { - assert(stmt->decl.var.ini); - *stmt->decl._cname = xasprintf("__s%s_%d", stmt->decl.name, id++); - genstatic(stmt->decl.externp, *stmt->decl._cname, &stmt->decl.var); - } - break; - case Dlet: - liftnestedex(stmt->decl.var.ini); - break; - default: - break; - } + liftdecl(&stmt->decl); break; case Sifelse: liftnested(stmt->ifelse.f); @@ -525,11 +548,8 @@ defctype(const struct type *ty, void *_) { if (!ty->_cname) switch (ty->t) { case TYvoid: case TYbool: - case TYint: case TYfloat: + case TYenum: case TYint: case TYfloat: break; - case TYenum: - defctype(ty->enu.intty, NULL); - return; case TYptr: defctype(ty->child, NULL); break; @@ -566,6 +586,11 @@ defctype(const struct type *ty, void *_) { case TYunion: kind = "union"; agg: + if (ty->konst) { + defctype(unconstify(ty), NULL); + *cname = (char *)unconstify(ty)->_cname; + break; + } *cname = xasprintf("__ty%s%d", ty->agg.name ? ty->agg.name : "", id++); pri("typedef %s %s %s;\n", kind, *cname, *cname); if (!ty->agg.fwd) { diff --git a/bootstrap/dump.c b/bootstrap/dump.c index 12a5a2a..8bec36d 100644 --- a/bootstrap/dump.c +++ b/bootstrap/dump.c @@ -164,14 +164,21 @@ vepri(const char *fmt, va_list ap) { int ws; for (char c; (c = *fmt++);) { + bool bold = 0; if (c != '%') { fputc(c, stderr); continue; } + again: + if (bold) + fprintf(stderr, "\x1b[1m"); switch ((c = *fmt++)) { case '%': fputc(c, stderr); break; + case 'b': + bold = 1; + goto again; case 'c': ch = bswap32(va_arg(ap, int)); while (ch) { @@ -226,6 +233,8 @@ vepri(const char *fmt, va_list ap) { abort(); break; } + if (bold) + fprintf(stderr, "\x1b[0m"); } } diff --git a/bootstrap/env.c b/bootstrap/env.c index 0c0021b..477c267 100644 --- a/bootstrap/env.c +++ b/bootstrap/env.c @@ -30,21 +30,37 @@ declscompatible(const struct decl *a, const struct decl *b) { return 0; } -bool +struct decl * envput(struct env *env, const struct decl *decl) { struct decls *decls; struct env env_noparent = { .decls = env->decls }; - struct decl *decl0; - if ((decl0 = envfind(&env_noparent, decl->name))) { - if (!declsshadowable(decl0, decl) && !declscompatible(decl0, decl)) - return 0; + struct decl *d0; + if ((d0 = envfind(&env_noparent, decl->name))) { + for (int kind = TYstruct; kind <= TYunion; ++kind) { + if (d0->t == Dtype && d0->ty->t == kind + && decl->t == Dtype && decl->ty->t == kind && d0->ty->agg.fwd) { + // modify existing forward declaration + *(size_t *)&d0->ty->size = decl->ty->size; + *(size_t *)&d0->ty->align = decl->ty->align; + *(bool *)&d0->ty->agg.fwd = 0; + memcpy((void *)&d0->ty->agg.flds, &decl->ty->agg.flds, + sizeof d0->ty->agg.flds); + memcpy((void *)&d0->ty->agg.decls, &decl->ty->agg.decls, + sizeof d0->ty->agg.decls); + d0->span = decl->span; + return d0; + } + } + if (!declsshadowable(d0, decl) && !declscompatible(d0, decl)) { + return NULL; + } } decls = xcalloc(1, sizeof *decls); decls->next = env->decls; decls->decl = *decl; env->decls = decls; - return 1; + return &decls->decl; } diff --git a/bootstrap/main.c b/bootstrap/main.c index 95759af..9432dcb 100644 --- a/bootstrap/main.c +++ b/bootstrap/main.c @@ -11,4 +11,5 @@ main(int argc, char **argv) { parse(&cf, &P); // dumptransunit(&tu); cgen(stdout, &cf); + // prialltypes(); } diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 381cfcc..025e061 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -413,6 +413,7 @@ lex(struct parser *P) { case '-': if (chrmatch(P, '=')) tok.t = '-='; else if (chrmatch(P, '-')) tok.t = '--'; + else if (chrmatch(P, '>')) tok.t = '->'; else tok.t = '-'; return tok; case '&': @@ -511,13 +512,15 @@ popenv(struct parser *P) { assert(P->curenv); } -static void +static struct decl * putdecl(struct parser *P, struct span espan, const struct decl *decl) { + struct decl *ret; if (envfind(P->primenv, decl->name)) fatal(P, espan, "cannot shadow primitive `%s'", decl->name); - if (!envput(P->curenv, decl)) + if (!(ret = envput(P->curenv, decl))) fatal(P, decl->span, "cannot shadow earlier incompatible declaration of `%s'", decl->name); + return ret; } static const struct decl * @@ -652,6 +655,8 @@ islvalue(const struct expr *ex) { return 1; if (ex->t == Eprefix && ex->unop.op == '*') return 1; + if (ex->t == Eindex || ex->t == Eget) + return 1; return 0; } @@ -683,14 +688,22 @@ structidx2fld(const struct type *ty, int idx) { static int structfldnam2idx(const struct type *ty, const char *name) { - int i; assert(name); - for (i = 0; i < ty->agg.flds.n; ++i) + for (int i = 0; i < ty->agg.flds.n; ++i) if (!strcmp(name, ty->agg.flds.d[i].name)) return i; return -1; } +static struct decl * +findaggdecl(const struct type *ty, const char *name) { + assert(name); + for (int i = 0; i < ty->agg.decls.n; ++i) + if (!strcmp(name, ty->agg.decls.d[i].name)) + return &ty->agg.decls.d[i]; + return NULL; +} + static struct expr parsestructini(struct parser *P, const struct type *ty) { struct expr ex = {Eini}; @@ -788,6 +801,8 @@ parsearrini(struct parser *P, const struct type *ty) { static const struct type * fntype(const struct fn *fn) { struct type ty = { TYfn, 0, g_targ.sizesize }; + if (fn->selfty) + return fn->selfty; vec_t(const struct type *) params = {0}; ty.fn.retty = fn->retty; for (int i = 0; i < fn->params.n; ++i) @@ -946,6 +961,7 @@ static struct expr pexpostfix(struct parser *P) { struct expr ex = pexprimary(P); struct tok tok; + struct fn *met = NULL; if (P->used_targty) return ex; @@ -954,6 +970,12 @@ pexpostfix(struct parser *P) { const struct type *ty = ex.ty; int i = 0; + if (met) { + ++i; + ty = met->selfty = fntype(met); + vec_push(&args, ex); + } + if (ty->t == TYptr) ty = ty->child; @@ -979,11 +1001,17 @@ pexpostfix(struct parser *P) { break; } } - ex.call.callee = exprdup(ex); - ex.t = Ecall; - ex.span = tok.span; - ex.ty = ty->fn.retty; - vec_slice_cpy(&ex.call.args, &args); + if (met) { + ex.t = Emcall; + ex.mcall.met = met; + vec_slice_cpy(&ex.mcall.args, &args); + } else { + ex.call.callee = exprdup(ex); + ex.t = Ecall; + ex.span = tok.span; + ex.ty = ty->fn.retty; + vec_slice_cpy(&ex.call.args, &args); + } } else if (lexmatch(P, &tok, '[')) { struct expr lhs = ex, rhs = parseexpr(P); @@ -1023,7 +1051,7 @@ pexpostfix(struct parser *P) { int idx = structfldnam2idx(ty, fnam); struct aggfield *fld = &ty->agg.flds.d[idx]; if (idx < 0) - fatal(P, tok.span, "%t has no such field `%s'", ex.ty, fnam); + fatal(P, tok.span, "%t has no such field `%s'", ty, fnam); ex.get.lhs = exprdup(ex); ex.t = Eget; @@ -1034,6 +1062,62 @@ pexpostfix(struct parser *P) { fatal(P, tok.span, "cannot access `%s': left-hand-side is not an aggregate (%t)", fnam, ex.ty); } + } else if (lexmatch(P, &tok, '->')) { + const char *fnam = (tok = lexexpect(P, TKident)).str; + const struct type *ty = ex.ty; + bool exptr = 0, metptr = 0; + + if ((exptr = ty->t == TYptr)) + ty = ty->child; + if (ty->t == TYstruct || ty->t == TYunion) { + struct decl *decl = findaggdecl(ty, fnam); + if (!decl) + fatal(P, tok.span, "%t has no such method `%s'", ty, fnam); + if (decl->t != Dfn) + fatal(P, tok.span, "%t:%bs is not a function", ty, fnam); + met = &decl->fn; + if (met->params.n == 0) + fatal(P, tok.span, + "cannot call `->%s', it takes zero arguments", + fnam); + + const struct type *recv0 = met->params.d[0].ty, + *recv = recv0; + if ((metptr = recv->t == TYptr)) + recv = recv->child; + if (unconstify(ty) != unconstify(recv)) + fatal(P, tok.span, + "method receiver type mismatch for `->%s' (%t vs %t)", + fnam, ty, recv); + if (!exptr && !metptr) { + ; + } else if (exptr && !metptr) { + ex = (struct expr) { + Eprefix, ex.span, ty, .unop = { '*', exprdup(ex) } + }; + } else if (!exptr && metptr) { + struct type pty = {TYptr, g_targ.ptrsize, 0, 0, .child = ty}; + if (!islvalue(&ex)) + fatal(P, tok.span, "cannot call `->%s' by reference: left-hand-side is not" + "an lvalue", fnam); + else if (ty->konst && !recv->konst) + fatal(P, tok.span, "constness mismatch: method takes %t but subject is %t", + recv0, ex.ty); + ex = (struct expr) { + Eprefix, ex.span, interntype(pty), .unop = { '&', exprdup(ex) } + }; + } else if (exptr && metptr) { + if (ty->konst && !recv->konst) + fatal(P, tok.span, "constness mismatch: method takes %t but subject is %t", + recv0, ex.ty); + } + + if (lexpeek(P).t != '(') + lexexpect(P, '('); + } else { + fatal(P, tok.span, "cannot call `->%s': left-hand-side is not an aggregate (%t)", + fnam, ex.ty); + } } else { break; } @@ -2076,7 +2160,6 @@ parseenum(struct parser *P, const char *name) { if (min >= INT32_MIN && max <= INT32_MAX) ty.enu.intty = ty_int; if (min >= INT64_MIN && max <= INT64_MAX) ty.enu.intty = ty_int; } - assert(ty.enu.intty); } ty.size = ty.enu.intty->size; @@ -2088,18 +2171,24 @@ parseenum(struct parser *P, const char *name) { } static const struct type * -parseagg(struct parser *P, const char *name, int kind) { +parseagg(struct parser *P, const char *name, int kind, bool *put) { struct tok tok; struct type ty = {kind}; + const struct type *pty = NULL; static int id = 0; size_t size = 0, align = 1; vec_t(struct aggfield) flds = {0}; + *put = 1; + if (lexmatch(P, &tok, ';')) { ty.agg.fwd = 1; } else { lexexpect(P, '{'); while (!lexmatch(P, &tok, '}')) { + if (isdecltokt(lexpeek(P).t)) + goto decls; + const char *fnam = (tok = lexexpect(P, TKident)).str; const struct type *ty = parsetype(P); size_t off = kind == TYunion ? 0 : ALIGNUP(size, ty->align); @@ -2129,6 +2218,41 @@ parseagg(struct parser *P, const char *name, int kind) { } } } + if (0) +decls: { + vec_t(struct decl) decls = {0}; + struct env env = {.parent = P->curenv}; + struct decl *decl; + + ty.size = ALIGNUP(size, align); + ty.align = align; + ty.agg.name = name; + vec_slice_cpy(&ty.agg.flds, &flds); + ty.agg.id = id++; + pty = interntype(ty); + if (name) + decl = putdecl(P, tok.span, + &(struct decl){Dtype, name, .span = tok.span, .ty = pty}); + if (decl->ty != pty) + uninterntype(pty); + pty = decl->ty; + + pushenv(P, &env); + while (!lexmatch(P, &tok, '}')) + parsedecl(NULL, NULL, P, 0); + for (struct decls *ds = env.decls, *next; ds; ds = next) { + if (ds->decl.t == Dtype && ds->decl.ty == pty) + ; + else + vec_push(&decls, ds->decl); + next = ds->next; + free(ds); + } + vec_slice_cpy(&((struct type *)decl->ty)->agg.decls, &decls); + popenv(P); + *put = 0; + return decl->ty; + } ty.size = ALIGNUP(size, align); ty.align = align; @@ -2184,7 +2308,8 @@ staticvaryield(struct decl *decl, void *arg) { if (a->P->is_header && a->externp && decl->var.ini) fatal(a->P, decl->span, "cannot define extern variable in header"); - a->yield(decl, a->yarg); + if (a->yield) + a->yield(decl, a->yarg); } static void @@ -2234,25 +2359,13 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) { decl.name = lexexpects(P, TKident, "enum name").str; decl.ty = parseenum(P, decl.name); } else if (lexmatch(P, &tok, TKkw_struct)) { - struct decl *d2; + bool put; kind = TYstruct; if (externp) fatal(P, tok.span, "struct cannot be `extern'"); agg: decl.name = lexexpects(P, TKident, "struct name").str; - decl.ty = parseagg(P, decl.name, kind); - d2 = (struct decl *)finddecl(P, decl.name); - if (d2 && d2->t == Dtype && d2->ty->t == kind && d2->ty->agg.fwd) { - // modify existing forward declaration - *(size_t *)&d2->ty->size = decl.ty->size; - *(size_t *)&d2->ty->align = decl.ty->align; - *(bool *)&d2->ty->agg.fwd = 0; - memcpy((void *)&d2->ty->agg.flds, &decl.ty->agg.flds, - sizeof d2->ty->agg.flds); - uninterntype(decl.ty); - d2->span = tok.span; - envput(P->curenv, d2); - return; - } + decl.ty = parseagg(P, decl.name, kind, &put); + if (!put) goto noput; } else if (lexmatch(P, &tok, TKkw_union)) { if (externp) fatal(P, tok.span, "union cannot be `extern'"); kind = TYunion; @@ -2265,7 +2378,8 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) { cf = doimport(P, path); for (int i = 0; i < cf.decls.n; ++i) { putdecl(P, tok.span, &cf.decls.d[i]); - yield(&cf.decls.d[i], yarg); + if (yield) + yield(&cf.decls.d[i], yarg); } free(cf.decls.d); lexexpect(P, ';'); @@ -2276,8 +2390,10 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) { } decl.span = tok.span; - putdecl(P, tok.span, &decl); - yield(&decl, yarg); + decl = *putdecl(P, tok.span, &decl); +noput: + if (yield) + yield(&decl, yarg); } static void diff --git a/bootstrap/test.cff b/bootstrap/test.cff index 011d386..7a6b7ce 100644 --- a/bootstrap/test.cff +++ b/bootstrap/test.cff @@ -1,12 +1,5 @@ import "libc.hff"; import "libc.hff"; - -struct Vec2f; -struct Vec2f { - x f32, - y f32, -} - union Val { x i64, lo i32, @@ -17,6 +10,13 @@ enum Color { Red, Green, Blue } +defmacro each(i, x, arr, ...body) [ + for let i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i { + let x = arr[i]; + { body } + } +] + static xs *void = {}, ok = 6; @@ -33,18 +33,36 @@ fn isort(xs *int, n usize) void { x(); } +struct Vec2f; +struct Vec2f { + x f32, + y f32, + + fn mag(v Vec2f) f32 { + extern fn sqrtf(_ f32) f32; + return sqrtf((v.x * v.x) + (v.y * v.y)); + } + fn zero(v *Vec2f) void { + v.x = 0; + v.y = 0; + } +} + extern fn main (argc int, argv **u8) int { let colors [3]Color = { :Red, :Green, :Blue } ; let x = Vec2f { .y: 1, .x: 2.4 }; - let p = &x; + let p *const Vec2f = &x; printf("v = { %g, %g }\n", x.x, p.y); + printf("mag = %g\n", x->mag()); + x->zero(); + printf("mag = %g\n", (&x)->mag()); let is [10]int = { [4] = 1, 2, [1 - 1] = 3 }; isort(is, 10); - for let i = 0; i < 10; ++i { - printf("%d\n", is[i]); - } + each(i, x, is, + printf("%d\n", x); + ) printf("sizeof(is) = %zu\n", sizeof(is)); printf("sizeof *void = %zu\n", sizeof *void); diff --git a/bootstrap/types.c b/bootstrap/types.c index 7b223f6..f826f9d 100644 --- a/bootstrap/types.c +++ b/bootstrap/types.c @@ -28,36 +28,42 @@ inittypes() { static u32 hashtype(const struct type *ty) { - u32 h = 0; - h = jkhashv(h, ty->t); - h = jkhashv(h, ty->size); - h = jkhashv(h, ty->align); - h = jkhashv(h, ty->konst); + u32 h = FNV1A_INI; + + h = fnv1ai(h, ty->t); + h = fnv1ai(h, ty->konst); + if (ty->t == TYfn) + epri(""); + switch (ty->t) { - case TYvoid: case TYbool: case TYfloat: + case TYvoid: case TYbool: break; - case TYint: - h = jkhashv(h, ty->int_signed); + case TYint: case TYfloat: + h = fnv1az(h, ty->size); + h = fnv1az(h, ty->align); + h = fnv1ai(h, ty->int_signed); break; case TYptr: case TYslice: - h = jkhashv(h, ty->child->_id); + assert(ty->child->size || ty->align == 1); + h = fnv1ai(h, ty->child->_id); break; case TYarr: - h = jkhashv(h, ty->child->_id); - h = jkhashv(h, ty->length); + assert(ty->child->size || ty->align == 1); + h = fnv1ai(h, ty->child->_id); + h = fnv1aI(h, ty->length); break; case TYfn: - h = jkhashv(h, ty->fn.retty->_id); - h = jkhashv(h, ty->fn.params.n); + h = fnv1ai(h, ty->fn.retty->_id); + h = fnv1ai(h, ty->fn.params.n); for (int i = 0; i < ty->fn.params.n; ++i) - h = jkhashv(h, ty->fn.params.d[i]->_id); + h = fnv1ai(h, ty->fn.params.d[i]->_id); break; case TYenum: - h = jkhashv(h, ty->enu.id); + h = fnv1ai(h, ty->enu.id); break; case TYstruct: case TYunion: case TYeunion: - h = jkhashv(h, ty->agg.id); + h = fnv1ai(h, ty->agg.id); break; } return h; @@ -67,15 +73,15 @@ bool typeeql(const struct type *lhs, const struct type *rhs) { if (lhs == rhs) return 1; - if (lhs->t != rhs->t || lhs->size != rhs->size - || lhs->align != rhs->align - || lhs->konst != rhs->konst) + if (lhs->t != rhs->t || lhs->konst != rhs->konst) return 0; switch (lhs->t) { - case TYvoid: case TYbool: case TYfloat: + case TYvoid: case TYbool: return 1; + case TYfloat: + return lhs->size == rhs->size; case TYint: - return lhs->int_signed == rhs->int_signed; + return lhs->size == rhs->size && lhs->int_signed == rhs->int_signed; case TYptr: case TYslice: return typeeql(lhs->child, rhs->child); @@ -139,6 +145,7 @@ typesput(const struct type *key) { nodes->next = types.buckets[idx]; types.buckets[idx] = nodes; } + idx = hash & (types.nbuckets - 1); } n->next = types.buckets[idx]; @@ -151,11 +158,14 @@ interntype(struct type ty) { static int id; if (!ty.align) ty.align = ty.size; + if ((ty.t == TYptr || ty.t == TYarr) && !ty.child->size) + ty.align = 1; const struct type *ty2 = typesfind(&ty); if (ty2) return ty2; ty._id = id++; ty2 = typesput(&ty); + // epri("new %t, h = %d. %d\n", ty2, hashtype(ty2), ty2->agg.id); assert(ty2); return ty2; } @@ -164,13 +174,15 @@ void uninterntype(const struct type *key) { u32 hash = hashtype(key); size_t idx = hash & (types.nbuckets - 1); - for (struct typesnode *n = types.buckets[idx], *prev = NULL; n; n = n->next) { + types.size--; + for (struct typesnode *n = types.buckets[idx], *prev = NULL; n; n = n->next) { if (key == &n->ty) { if (prev) { prev->next = n->next; } else { types.buckets[idx] = n->next; } + free(n); break; } prev = n; @@ -384,3 +396,14 @@ typeof2(const struct type *a, const struct type *b) { } return NULL; } + + +void +prialltypes(void) { + for (int i = 0; i < types.nbuckets; ++i) { + epri("bkt %d:\n", i); + for (struct typesnode *n = types.buckets[i]; n; n = n->next) { + epri(" %t : %d\n", &n->ty, hashtype(&n->ty)); + } + } +} diff --git a/bootstrap/util.c b/bootstrap/util.c index c9be845..bd6f951 100644 --- a/bootstrap/util.c +++ b/bootstrap/util.c @@ -1,18 +1,15 @@ #include "all.h" -// Bob Jenkins's one_at_a_time hash u32 -jkhash(u32 h, const u8 *data, size_t length) { +fnv1a(u32 h, const void *p, size_t length) { + const u8 *data = p; size_t i = 0; + u64 H = h; while (i != length) { - h += data[i++]; - h += h << 10; - h ^= h >> 6; + H ^= data[i++]; + H *= 0x100000001b3; } - h += h << 3; - h ^= h >> 11; - h += h << 15; - return h; + return H; } static const char *filepaths[100]; @@ -117,7 +114,7 @@ eprifileline(struct span span) { --j; n = fprintf(stderr, "%4d| ", span.line); - for (long k = i; k < j; ++k) + for (long k = i; k <= j; ++k) epri("%c", src[k]); epri("\n"); while (n--) |