diff options
| author | 2022-08-14 11:16:03 +0200 | |
|---|---|---|
| committer | 2022-08-14 11:16:03 +0200 | |
| commit | 0d1e125832d0fd8ca31c5f782e7c3db774ae5a02 (patch) | |
| tree | e4622f75a8307d8ee1970f8bd6cc92766582f0ba | |
| parent | c129f77ad724aa940b53a125de0e1e4de0ca7240 (diff) | |
woa
| -rw-r--r-- | bootstrap/all.h | 1 | ||||
| -rw-r--r-- | bootstrap/cgen.c | 8 | ||||
| -rw-r--r-- | bootstrap/env.c | 4 | ||||
| -rw-r--r-- | bootstrap/parse.c | 17 | ||||
| -rw-r--r-- | examples/ack.cff (renamed from bootstrap/ack.cff) | 0 | ||||
| -rw-r--r-- | examples/libc.hff | 32 | ||||
| -rw-r--r-- | src/cffc.hff (renamed from src/all.hff) | 62 | ||||
| -rw-r--r-- | src/common.hff | 45 | ||||
| -rw-r--r-- | src/env.cff | 3 | ||||
| -rw-r--r-- | src/fmt.cff | 25 | ||||
| -rw-r--r-- | src/main.cff | 5 | ||||
| -rw-r--r-- | src/map.hff | 5 | ||||
| -rw-r--r-- | src/mem.hff | 3 | ||||
| -rw-r--r-- | src/parse.cff | 23 | ||||
| -rw-r--r-- | src/set.hff | 36 | ||||
| -rw-r--r-- | src/targ.cff | 3 | ||||
| -rw-r--r-- | src/targ.hff | 12 | ||||
| -rw-r--r-- | src/type.cff | 3 | ||||
| -rw-r--r-- | src/type.hff | 15 | ||||
| -rw-r--r-- | src/util.cff | 5 | ||||
| -rw-r--r-- | src/util.hff | 12 | ||||
| -rw-r--r-- | src/vec.hff | 9 |
22 files changed, 224 insertions, 104 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h index 9bbab37..bb0711a 100644 --- a/bootstrap/all.h +++ b/bootstrap/all.h @@ -290,6 +290,7 @@ struct decl { int loopid; }; int age; + bool _gen; }; struct teplparam { diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c index 5c64a30..39cbba0 100644 --- a/bootstrap/cgen.c +++ b/bootstrap/cgen.c @@ -50,7 +50,11 @@ pristring(const char *s, u64 n) { extern int isprint(int); pri("\""); for (int i = 0; i < n; ++i) { - if (isprint(s[i])) + if (s[i] == '"') + pri("\\\""); + else if (s[i] == '\\') + pri("\\\\"); + else if (isprint(s[i])) pri("%c", s[i]); else fprintf(outfp, "\\%.3o", s[i]); @@ -699,6 +703,7 @@ genstatic(bool externp, const char *cname, struct var *var) { static void gendecl(struct decl *decl, bool toplevel) { const char *p = fileid2path(decl->span.fileid); + if (decl->_gen) return; switch (decl->t) { case Dfn: pri("#line %d %S\n", decl->span.line, p, (u64)strlen(p)); @@ -718,6 +723,7 @@ gendecl(struct decl *decl, bool toplevel) { case Dtype: case Ddef: case Dtepl: case Dmacro: case Dlabel: break; } + decl->_gen = 1; } static void diff --git a/bootstrap/env.c b/bootstrap/env.c index 40392b9..21d9580 100644 --- a/bootstrap/env.c +++ b/bootstrap/env.c @@ -42,6 +42,10 @@ envput(struct env *env, const struct decl *decl) { return d0; if (d0->t == Dmacro && !memcmp(&decl->macro, &d0->macro, sizeof decl->macro)) return d0; + if (d0->t == Dtype && d0->ty == decl->ty) + return d0; + if (d0->t == Dfn && !memcmp(&decl->fn, &d0->fn, sizeof decl->fn)) + return d0; if (d0->t == Dtepl && !memcmp(&decl->tepl, &d0->tepl, sizeof decl->tepl)) return d0; for (int kind = TYstruct; kind <= TYeunion; ++kind) { diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 4a1721d..0c619fc 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -2925,7 +2925,7 @@ getbasedir(const char *path) { static struct comfile doimport(struct parser *P, const char *path) { - static vec_t(struct entry { const char *s; struct comfile cf; }) seen; + static vec_t(struct entry { const char *s; struct comfile cf; bool wip; }) seen; char path2[PATH_MAX], _rpath[PATH_MAX], *rpath; struct comfile cf = {0}; struct parser P2; @@ -2934,16 +2934,23 @@ doimport(struct parser *P, const char *path) { if (!(rpath = realpath(path2, _rpath))) fatal(P, P->tokspan, "import %q: %s", path, strerror(errno)); - for (int i = 0; i < seen.length; ++i) - if (!strcmp(seen.data[i].s, rpath)) - return seen.data[i].cf; + for (int i = 0; i < seen.length; ++i) { + if (!strcmp(seen.data[i].s, rpath)) { + if (seen.data[i].wip) { + epri("warning: \"%s\": circular import detected: \"%s\" being processed\n", + P->curfile, path); + } + return seen.data[i].cf; + } + } rpath = xstrdup(rpath); // P2.primenv = P->primenv; initparser(&P2, rpath); P2.is_header = 1; - vec_push(&seen, ((struct entry) { rpath, cf })); + vec_push(&seen, ((struct entry) { rpath, cf, 1 })); parse(&cf, &P2); + seen.data[seen.length - 1].wip = 0; seen.data[seen.length - 1].cf = cf; return cf; } diff --git a/bootstrap/ack.cff b/examples/ack.cff index 233abc2..233abc2 100644 --- a/bootstrap/ack.cff +++ b/examples/ack.cff diff --git a/examples/libc.hff b/examples/libc.hff new file mode 100644 index 0000000..488a495 --- /dev/null +++ b/examples/libc.hff @@ -0,0 +1,32 @@ +// stdio.h +struct FILE; +extern static stdin *FILE, + stdout *FILE, + stderr *FILE; +extern fn printf(fmt *const u8, ...) int; +extern fn fprintf(fp *FILE, fmt *const u8, ...) int; +extern fn sprintf(*u8, fmt *const u8, ...) int; +extern fn snprintf(*u8, usize, fmt *const u8, ...) int; +extern fn fopen(path *const u8, mode *const u8) *FILE; +extern fn fclose(*FILE) int; +extern fn fgetc(*FILE) int; +extern fn fputc(int, *FILE) int; +def EOF = -1; + +// stdlib.h +extern fn abort() void; +extern fn exit(c int) void; +extern fn perror(s *const u8) void; +extern fn malloc(n usize) *void; +extern fn calloc(n usize, m usize) *void; +extern fn realloc(p *void, n usize) *void; +extern fn free(p *void) void; + +// string.h +extern fn strlen(s *const u8) usize; +extern fn strcmp(a *const u8, b *const u8) int; +extern fn memcpy(*void, *const void, usize) *void; +extern fn strcpy(*u8, *const u8) *u8; + +//ctype.h +extern fn tolower(int) int; diff --git a/src/all.hff b/src/cffc.hff index 4ae3e26..dcb91f7 100644 --- a/src/all.hff +++ b/src/cffc.hff @@ -1,34 +1,7 @@ -import "mem.hff"; import "libc.hff"; +import "mem.hff"; import "option.hff"; -/// Macros - -defmacro assert { -(ex, s, ...args) [ - (do - if not (ex) { - fprintf(stderr, "%s:%d: assertion failed: ", #FILE, #LINE); - fprintf(stderr, s, args); - fprintf(stderr, "\n"); - abort(); - } - ) -] -} - -defmacro foreach(x, i, a, ...body) [ - { - let $a = a; - for let i = 0; i < $a.#len; ++i { - let x = $a[i]; - { body } - } - } -] - -defmacro streq(a,b) [ (strcmp(a,b) == 0) ] - /// Types struct Type; @@ -138,25 +111,15 @@ struct Targ { extern fn parser_init(*Parser, path *const u8) void; extern fn parse(*Parser) [#]Decl; -// util.cff -extern fn xmalloc(n usize) *void; -extern fn xcalloc(n usize, m usize) *void; -extern fn xrealloc(p *void, n usize) *void; -extern fn xstrdup(str *const u8) *u8; -def FNV1A_INI u32 = 0x811c9dc5; -extern fn fnv1a(h u32, [#]const u8) u32; -extern fn fnv1a_s(h u32, *const u8) u32; -extern fn fnv1a_i(h u32, i64) u32; -extern fn addfilepath(*const u8) int; -extern fn fatal(*Parser, Loc, fmt *const u8, ...) void; -extern fn internstr(*const u8) *const u8; - // fmt.cff extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, va_list) void; extern fn pfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ...) void; extern fn vefmt(fmt *const u8, ap va_list) void; extern fn efmt(fmt *const u8, ...) void; +// .. util.cff .. +extern fn fatal(*Parser, Loc, fmt *const u8, ...) void; + // type.cff // env.cff @@ -166,20 +129,3 @@ extern fn envput(*Env, *const Decl) *Decl; // targ.cff extern static g_targ *const Targ; extern fn targ_ini(name *const u8) bool; - -// Inline functions -fn bswap32(x u32) u32 { - return (x >> 24) - | ((x >> 8) & 0x00FF00) - | ((x << 8) & 0xFF0000) - | (x << 24); -} - -fn bswap64(x u64) u64 { - return (as(u64)bswap32(x) << 32) - | (bswap32(x >> 32)); -} - -fn spanz(x *const u8) [#]const u8 { - return x[0::strlen(x)]; -} diff --git a/src/common.hff b/src/common.hff new file mode 100644 index 0000000..aac733e --- /dev/null +++ b/src/common.hff @@ -0,0 +1,45 @@ +import "libc.hff"; + +/// Macros + +defmacro assert { +(ex, s, ...args) [ + (do + if not (ex) { + fprintf(stderr, "%s:%d: assertion failed: ", #FILE, #LINE); + fprintf(stderr, s, args); + fprintf(stderr, "\n"); + abort(); + } + ) +] +} + +defmacro foreach(x, i, a, ...body) [ + { + let $a = a; + for let i = 0; i < $a.#len; ++i { + let x = $a[i]; + { body } + } + } +] + +defmacro streq(a,b) [ (strcmp(a,b) == 0) ] + +// Inline functions +fn bswap32(x u32) u32 { + return (x >> 24) + | ((x >> 8) & 0x00FF00) + | ((x << 8) & 0xFF0000) + | (x << 24); +} + +fn bswap64(x u64) u64 { + return (as(u64)bswap32(x) << 32) + | (bswap32(x >> 32)); +} + +fn spanz(x *const u8) [#]const u8 { + return x[0::strlen(x)]; +} diff --git a/src/env.cff b/src/env.cff index 8878238..d1eab07 100644 --- a/src/env.cff +++ b/src/env.cff @@ -1,5 +1,6 @@ +import "cffc.hff"; import "map.hff"; -import "all.hff"; +import "util.hff"; struct StringKeyTraits { fn hash(s *const u8) u32 { return fnv1a_s(FNV1A_INI, s); } diff --git a/src/fmt.cff b/src/fmt.cff index 8212593..90fcd47 100644 --- a/src/fmt.cff +++ b/src/fmt.cff @@ -1,4 +1,5 @@ -import "all.hff"; +import "cffc.hff"; +import "common.hff"; extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) void { defmacro p(x) [ proc(x, parg) ] @@ -10,14 +11,22 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) defmacro pch(ch) [ { extern fn isprint(int) int; - let $ch = ch; - if isprint($ch) != 0 { + let $ch u8 = ch; + switch { + case $ch == '\''; + ps("\\'"); + case $ch == '\"'; + ps("\\\""); + case $ch == '\\'; + ps("\\\\"); + case isprint($ch) != 0; p($ch); - } else { - p('\\'); - p('0' + ($ch % 8)); - p('0' + (($ch / 8) % 8)); - p('0' + (($ch / 8 / 8) % 8)); + case $ch == '\n'; + ps("\\n"); + case else; + ps("\\x"); + p("0123456789ABCDEF"[($ch >> 4) & 15]); + p("0123456789ABCDEF"[$ch & 15]); } } ] diff --git a/src/main.cff b/src/main.cff index 596a411..7cc90a0 100644 --- a/src/main.cff +++ b/src/main.cff @@ -1,6 +1,5 @@ -import "all.hff"; -import "libc.hff"; -import "vec.hff"; +import "cffc.hff"; +import "common.hff"; extern fn main(argc int, argv **u8) int { assert(argc > 1, "args?"); diff --git a/src/map.hff b/src/map.hff index 87d0506..d7883dd 100644 --- a/src/map.hff +++ b/src/map.hff @@ -1,4 +1,5 @@ -import "all.hff"; +import "common.hff"; +import "util.hff"; // KTraits: // :hash(K) u32 @@ -32,6 +33,8 @@ struct Map<K, V, KTraits> { } fn _reallockvb(self *Map) void { + // keys, vals, bitmap are in a contiguous memory allocation, + // XXX ^ alignment let p = xcalloc((self.N * (sizeof K + sizeof V)) + (self.N / 8), 1); self.keys = p; self.vals = as(*V)(self.keys + self.N); diff --git a/src/mem.hff b/src/mem.hff index a86bee3..805c3ce 100644 --- a/src/mem.hff +++ b/src/mem.hff @@ -1,8 +1,7 @@ import "libc.hff"; -import "all.hff"; -def ARENA_SIZE = 16 * 1024; defmacro ALIGNUP(x,a) [ (((x) + ((a) - 1)) & -(a)) ] +def ARENA_SIZE = 16 * 1024; extern fn xmalloc(n usize) *void; extern fn xcalloc(n usize, m usize) *void; extern fn xrealloc(p *void, n usize) *void; diff --git a/src/parse.cff b/src/parse.cff index 0843ccf..25a2617 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -1,5 +1,7 @@ +import "mem.hff"; +import "util.hff"; import "vec.hff"; -import "all.hff"; +import "cffc.hff"; /////////// // Lexer // @@ -164,6 +166,15 @@ fn str2keyword(s *const u8) int { return -1; } +fn xdigit2num(c u8) int { + switch { + case isdigit(c); return c - '0'; + case c >= 'a' and c <= 'f'; return (c - 'a') + 10; + case c >= 'A' and c <= 'F'; return (c - 'A') + 10; + } + return -1; +} + fn readnumber(s *const u8) Option<Tok> { let c u8 #?, acc = 0u64, @@ -198,8 +209,7 @@ fn readnumber(s *const u8) Option<Tok> { accf = accf + ((c - '0') * fmul); fmul *= 0.1; } else { - c = tolower(c); - acc = (acc * base) + (c <= '9' ? c - '0' : (c - 'a') + 10); + acc = (acc * base) + xdigit2num(c); } } @@ -323,6 +333,13 @@ fn lex(P *Parser) Tok { case 'r'; str->push('\r'); case 't'; str->push('\t'); case 'v'; str->push('\v'); case 'f'; str->push('\f'); case '0'; str->push('\0'); + case 'x'; + let x0 = xdigit2num(chr(P)), + x1 = xdigit2num(chr(P)); + if x0 < 0 or x1 < 0 { + fatal(P, P.tokloc, "not a hex byte escape sequence"); + } + str->push((x0 << 4) | x1); case else fatal(P, P.tokloc, "unknown escape sequence '\\%c'", c); } diff --git a/src/set.hff b/src/set.hff index 6ab44ea..82c213f 100644 --- a/src/set.hff +++ b/src/set.hff @@ -1,5 +1,4 @@ import "vec.hff"; -import "all.hff"; #{ Traits:hash(K) u32 @@ -12,6 +11,12 @@ struct Set<T, Traits> { N int, count int, + + fn _nexthash(h *u32) u32 { + // return *h = (*h * 1664525) + 1013904223u; // double hashing + return ++*h; // linear probing + } + fn intern(self *Set, x T) *const T { if self.set == #null { self.set = xcalloc(self.N = 16, sizeof int); @@ -21,20 +26,22 @@ struct Set<T, Traits> { free(self.set); self.set = xcalloc(self.N *= 2, sizeof int); vec_each(p, i, self.buf, - let j = Traits:hash(p) & (self.N - 1); + let h = Traits:hash(p); + let j = h & (self.N - 1); for ;; { if self.set[j] == 0 { self.set[j] = i + 1; break; } - j = (j + 1) & (self.N - 1); + j = _nexthash(&h) & (self.N - 1); } ) } - let i0 u32 = Traits:hash(x) & (self.N - 1); - let i int = i0; - do { + let h u32 = Traits:hash(x); + let i = h & (self.N - 1) & (self.N - 1); + let n = 0; + for ;; { if self.set[i] == 0 { ++self.count; self.buf->push(Traits:dup(x)); @@ -46,23 +53,22 @@ struct Set<T, Traits> { return x2; } } - i = (i + 1) & (self.N - 1); - } while i != i0; - assert(#f, "unreachable"); + ++n; + i = _nexthash(&h) & (self.N - 1); + } } fn contains(self *Set, x T) bool { - let i0 u32 = Traits:hash(x) & (self.N - 1); - let i int = i0; - do { + let h u32 = Traits:hash(x); + let i = h & (self.N - 1); + for ;; { if self.set[i] == 0 { return #f; } else if Traits:eq(self.buf.dat[self.set[i] - 1], x) { return #t; } - i = (i + 1) & (self.N - 1); - } while i != i0; - assert(#f, "unreachable"); + i = _nexthash(&h) & (self.N - 1); + } } fn put(self *Set, x T) void { diff --git a/src/targ.cff b/src/targ.cff index 6490dff..59078a0 100644 --- a/src/targ.cff +++ b/src/targ.cff @@ -1,4 +1,5 @@ -import "all.hff"; +import "cffc.hff"; +import "common.hff"; static const targs []const Targ = { { diff --git a/src/targ.hff b/src/targ.hff new file mode 100644 index 0000000..9df8ee5 --- /dev/null +++ b/src/targ.hff @@ -0,0 +1,12 @@ +struct Targ { + name *const u8, + ptrsize u8, + intsize u8, + longsize u8, longalign u8, + llongsize u8, llongalign u8, + sizesize u8, + f64align u8, + valistsize u8, valistalign u8, + charsigned bool, + shortenum bool, +} diff --git a/src/type.cff b/src/type.cff index a6987b7..a3c7021 100644 --- a/src/type.cff +++ b/src/type.cff @@ -1,4 +1,5 @@ -import "all.hff"; +import "cffc.hff"; +import "util.hff"; fn hashtype(ty *const Type) u32 { let h = FNV1A_INI; diff --git a/src/type.hff b/src/type.hff new file mode 100644 index 0000000..ce04063 --- /dev/null +++ b/src/type.hff @@ -0,0 +1,15 @@ +struct Type { + size usize, + align usize, + konst bool, + id uint, + u enum union { + Void, + Bool, + Int struct { sgn bool }, + Flo, + Ptr *Type, + Arr struct { child *Type, length i64 }, + Slice *Type, + } +} diff --git a/src/util.cff b/src/util.cff index 18305b2..1b81ab4 100644 --- a/src/util.cff +++ b/src/util.cff @@ -1,5 +1,8 @@ +import "util.hff"; +import "cffc.hff"; import "set.hff"; -import "all.hff"; +import "mem.hff"; +import "common.hff"; extern fn xmalloc(n usize) *void { let p = malloc(n); diff --git a/src/util.hff b/src/util.hff new file mode 100644 index 0000000..5eb9c88 --- /dev/null +++ b/src/util.hff @@ -0,0 +1,12 @@ +// util.cff +extern fn xmalloc(n usize) *void; +extern fn xcalloc(n usize, m usize) *void; +extern fn xrealloc(p *void, n usize) *void; +extern fn xstrdup(str *const u8) *u8; +def FNV1A_INI u32 = 0x811c9dc5; +extern fn fnv1a(h u32, [#]const u8) u32; +extern fn fnv1a_s(h u32, *const u8) u32; +extern fn fnv1a_i(h u32, i64) u32; +extern fn addfilepath(*const u8) int; +// extern fn fatal(*Parser, Loc, fmt *const u8, ...) void; +extern fn internstr(*const u8) *const u8; diff --git a/src/vec.hff b/src/vec.hff index 35a9331..7f012aa 100644 --- a/src/vec.hff +++ b/src/vec.hff @@ -1,6 +1,7 @@ -import "all.hff"; +import "common.hff"; +import "mem.hff"; +import "util.hff"; -extern fn malloc(n usize) *void; struct Vec<T> { dat *T, len uint, @@ -10,10 +11,10 @@ struct Vec<T> { if vec.len >= vec.cap { vec.cap = (vec.len + 1) > 8 ? (vec.len + 1) * 2 : 8; if vec.dat == #null { - vec.dat = malloc(vec.cap * sizeof T); + vec.dat = xmalloc(vec.cap * sizeof T); assert(vec.dat != #null, "malloc"); } else { - vec.dat = realloc(vec.dat, vec.cap * sizeof T); + vec.dat = xrealloc(vec.dat, vec.cap * sizeof T); assert(vec.dat != #null, "realloc"); } } |