diff options
Diffstat (limited to 'src/tools/zc0.c')
| -rw-r--r-- | src/tools/zc0.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/src/tools/zc0.c b/src/tools/zc0.c index 5f5b97d..b0ab29f 100644 --- a/src/tools/zc0.c +++ b/src/tools/zc0.c @@ -202,7 +202,7 @@ static void expect(const char *s) { if (!accept(s)) { char b[64]; sprintf(b, "ex static char *ident(void) { static char b[8][256]; static int k; char *r = b[k++ & 7]; if (tk != T_ID) die("expected a name"); strcpy(r, ts); next(); return r; } /* ---- symbols ---- */ -typedef struct { char name[64]; int kind, sig, defd; int64_t val; } Sym; +typedef struct { char name[64]; int kind, sig, defd, str; int64_t val; } Sym; /* str: a global holding a byte string */ static Sym sy[16384]; static int nsy; typedef struct { int at, sym; } Fix; static Fix fx[65536]; static int nfx; @@ -225,7 +225,7 @@ static Sym *add(const char *n, int kind, int64_t val) char full[256]; qualify(full, sizeof full, n); n = full; Sym *s = find_raw(n); if (s && s->kind == K_FN && kind == K_FN && !s->defd) { s->val = val; return s; } /* prototype or forward use */ - s = &sy[nsy++]; strncpy(s->name, n, 63); s->kind = kind; s->val = val; s->defd = 1; s->sig = 0; return s; + s = &sy[nsy++]; strncpy(s->name, n, 63); s->kind = kind; s->val = val; s->defd = 1; s->sig = 0; s->str = 0; return s; } static void fnref(const char *n) /* push a function address, fixing it up later if needed */ { @@ -488,7 +488,7 @@ static void primary(void) if ((l = findl(n))) { laddr(l->slot); lv = !l->arr; if (!l->arr) { xf = l->flt; xs = l->str; lvi = (int)(l - lo); } return; } s = find(n); if (s && s->kind == K_CONST) { lit(s->val); return; } - if (s && s->kind == K_GVAR) { lit(s->val); lv = 1; return; } + if (s && s->kind == K_GVAR) { lit(s->val); lv = 1; xs = s->str; return; } if (s && s->kind == K_GARR) { lit(s->val); return; } if (is("(")) { int na = args(); @@ -799,8 +799,11 @@ static void enhdef(void) /* embed "path" as [type] name; at the top level: a global holding the file's bytes, read when the image is built. the path is relative to the working directory. bstr (the default) packs the bytes; char* keeps one character to a word; a - number takes them little-endian; T[] and T[n] lay them out as the array's - elements. the same rules as the resident compiler's kw_embed. */ + number takes them little-endian; T[] and T[n] have one element per file chunk + of T's size. the checks are the resident compiler's (kw_embed). zc0 drops + types, so its arrays are one word per element whatever T is: an element is + stored as the value it reads as (sign extended for i8, i16 and i32, widened + for f32), and zc0 code indexing the array sees the same values. */ static int embed_width(const char *t, int star) { if (star) return 0; @@ -832,7 +835,7 @@ static void embeddecl(void) if (!buf || fread(buf, 1, (size_t)len, f) != (size_t)len) die("can't read the file named by embed"); fclose(f); if (arr == -2 && (!ty[0] || (!strcmp(ty, "bstr") && !star))) { - a = here; add(n, K_GVAR, a); emit(0); img[a - GORG] = here; emit(len); + a = here; add(n, K_GVAR, a)->str = 1; emit(0); img[a - GORG] = here; emit(len); for (i = 0; i < len; i += 8) { uint64_t u = 0; for (w = 0; w < 8 && i + w < len; w++) u |= (uint64_t)buf[i + w] << (w * 8); emit((int64_t)u); } if (!(len & 7)) emit(0); } else if (arr == -2 && !strcmp(ty, "char") && star == 1) { @@ -857,12 +860,14 @@ static void embeddecl(void) if (arr >= 0 && count > arr) die("the embedded file is larger than the array it is declared as"); if (arr >= 0) count = arr; a = here; - if (!strcmp(ty, "char")) { for (i = 0; i < count; i++) emit(i < len ? buf[i] : 0); } - else { - long bytes = (long)count * w; - for (i = 0; i < bytes; i += 8) { uint64_t u = 0; for (int k = 0; k < 8 && i + k < bytes; k++) u |= (uint64_t)(i + k < len ? buf[i + k] : 0) << (k * 8); emit((int64_t)u); } - if (!bytes) emit(0); + for (i = 0; i < count; i++) { + uint64_t u = 0; int k; + for (k = 0; k < w && (long)i * w + k < len; k++) u |= (uint64_t)buf[(long)i * w + k] << (k * 8); + if (ty[0] == 'i' && w < 8 && (u >> (w * 8 - 1) & 1)) u |= ~(uint64_t)0 << (w * 8); + if (!strcmp(ty, "f32")) u = fop_s2f(u); + emit((int64_t)u); } + if (!count) emit(0); add(n, K_GARR, a); } free(buf); |
