aboutsummaryrefslogtreecommitdiff
path: root/src/tools/zc0.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/zc0.c')
-rw-r--r--src/tools/zc0.c27
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);