summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-12-27 15:33:28 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-12-27 15:33:28 -0500
commit5c23113aa2631bd4d1ef71c4964bf32f7daf1010 (patch)
tree3a116c6b290b6c1cfd5af7ef7ffa266c6158f82d
parent1b12d3410e0426f3772564ff8439dd0c5f9a7186 (diff)
more work on exporting (floats), discovered bug
-rw-r--r--binfile.c96
-rw-r--r--err.c18
-rw-r--r--package.c44
-rw-r--r--parse.c2
-rw-r--r--test.toc2
5 files changed, 144 insertions, 18 deletions
diff --git a/binfile.c b/binfile.c
index 9ca175b..a1e8269 100644
--- a/binfile.c
+++ b/binfile.c
@@ -5,9 +5,7 @@ static inline void write_u8(FILE *fp, U8 u8) {
}
static inline void write_i8(FILE *fp, I8 i8) {
- U8 byte = (U8)(i8 < 0 ? -i8 : +i8);
- if (i8 < 0) byte |= 0x80;
- putc(byte, fp);
+ write_u8(fp, (U8)i8);
}
/*
@@ -21,8 +19,7 @@ static inline void write_u16(FILE *fp, U16 u16) {
}
static inline void write_i16(FILE *fp, I16 i16) {
- write_u8(fp, (U8)(i16 & 0xFF));
- write_i8(fp, (I8)(i16 / 0x100)); /* division is necessary here to keep sign */
+ write_u16(fp, (U16)i16);
}
static inline void write_u32(FILE *fp, U32 u32) {
@@ -31,8 +28,7 @@ static inline void write_u32(FILE *fp, U32 u32) {
}
static inline void write_i32(FILE *fp, I32 i32) {
- write_u16(fp, (U16)(i32 & 0xFFFF));
- write_i16(fp, (I16)(i32 / 0x10000));
+ write_u32(fp, (U32)i32);
}
static void write_u64(FILE *fp, U64 u64) {
@@ -44,10 +40,9 @@ static void write_u64(FILE *fp, U64 u64) {
#endif
}
-static void write_i64(FILE *fp, I64 i64) {
+static inline void write_i64(FILE *fp, I64 i64) {
#if BINFILE_PORTABLE
- write_u32(fp, (U32)(i64 & 0xFFFFFFFF));
- write_i32(fp, (I32)(i64 / 0x100000000));
+ write_u64(fp, (U64)i64);
#else
fwrite(&i64, sizeof i64, 1, fp);
#endif
@@ -55,7 +50,40 @@ static void write_i64(FILE *fp, I64 i64) {
static void write_f32(FILE *fp, F32 f32) {
#if BINFILE_PORTABLE
- /* TODO */
+ /* writes as IEEE 754 32-bit floating-point number, little endian */
+ /* TODO: infinity, NaN */
+ U32 fraction = 0;
+ U32 fraction_bit = ((U32)1) << 22;
+ unsigned exponent = 127;
+ unsigned sign = f32 < 0;
+ if (sign) f32 = -f32;
+ while (f32 < (F32)1) {
+ f32 *= (F32)2;
+ --exponent;
+ }
+ while (f32 > (F32)2) {
+ f32 /= (F32)2;
+ ++exponent;
+ }
+ if (f32 > (F32)1) --f32;
+ f32 *= (F32)2;
+ while (fraction_bit) {
+ if (((U32)f32)) {
+ assert((U32)f32 == 1);
+ fraction |= fraction_bit;
+ --f32;
+ }
+ f32 *= (F32)2;
+ fraction_bit >>= 1;
+ }
+ putc(fraction & 0xFF, fp);
+ putc((fraction & 0xFF00) >> 8, fp);
+ unsigned byte3 = (fraction & 0x7F0000) >> 16;
+ byte3 |= (exponent & 1) << 7;
+ putc((int)byte3, fp);
+ unsigned byte4 = exponent >> 1;
+ byte4 |= (sign << 7);
+ putc((int)byte4, fp);
#else
fwrite(&f32, sizeof f32, 1, fp);
#endif
@@ -63,8 +91,52 @@ static void write_f32(FILE *fp, F32 f32) {
static void write_f64(FILE *fp, F64 f64) {
#if BINFILE_PORTABLE
- /* TODO */
+ U64 fraction = 0;
+ U64 fraction_bit = ((U64)1) << 51;
+ unsigned exponent = 1023;
+ unsigned sign = f64 < 0;
+ if (sign) f64 = -f64;
+ while (f64 < (F64)1) {
+ f64 *= (F64)2;
+ --exponent;
+ }
+ while (f64 > (F64)2) {
+ f64 /= (F64)2;
+ ++exponent;
+ }
+ if (f64 > (F64)1) --f64;
+ f64 *= (F64)2;
+ while (fraction_bit) {
+ if (((U64)f64)) {
+ assert((U64)f64 == 1);
+ fraction |= fraction_bit;
+ --f64;
+ }
+ f64 *= (F64)2;
+ fraction_bit >>= 1;
+ }
+ printf("%lu\n",fraction);
+ putc(fraction & 0xFF, fp);
+ putc((fraction & 0xFF00) >> 8, fp);
+ putc((fraction & 0xFF0000) >> 16, fp);
+ putc((fraction & 0xFF000000) >> 24, fp);
+ putc((fraction & 0xFF00000000) >> 32, fp);
+ putc((fraction & 0xFF0000000000) >> 40, fp);
+ unsigned byte7 = (fraction & 0xF000000000000) >> 48;
+ byte7 |= (exponent & 0xF) << 4;
+ putc((int)byte7, fp);
+ unsigned byte8 = (exponent & 0x7F0) >> 4;
+ byte8 |= (sign << 7);
+ putc((int)byte8, fp);
#else
fwrite(&f64, sizeof f64, 1, fp);
#endif
}
+
+static void write_bool(FILE *fp, bool b) {
+ putc(b, fp);
+}
+
+static void write_char(FILE *fp, char c) {
+ putc(c, fp);
+}
diff --git a/err.c b/err.c
index a92a143..58279f5 100644
--- a/err.c
+++ b/err.c
@@ -123,7 +123,7 @@ static void err_print_(
va_list args;
if (!where.ctx->enabled) return;
#if ERR_SHOW_SOURCE_LOCATION
- if (file)
+ if (file)
err_fprint("Generated by line %d of %s:\n", line, file);
#endif
va_start(args, fmt);
@@ -147,9 +147,17 @@ static void info_print(Location where, const char *fmt, ...) {
va_end(args);
}
-static void warn_print(Location where, const char *fmt, ...) {
+static void warn_print_(
+#if ERR_SHOW_SOURCE_LOCATION
+ int line, const char *file,
+#endif
+ Location where, const char *fmt, ...) {
va_list args;
if (!where.ctx->enabled) return;
+#if ERR_SHOW_SOURCE_LOCATION
+ if (file)
+ err_fprint("Generated by line %d of %s:\n", line, file);
+#endif
va_start(args, fmt);
warn_print_header_(where);
err_vfprint(fmt, args);
@@ -157,6 +165,12 @@ static void warn_print(Location where, const char *fmt, ...) {
va_end(args);
}
+#if ERR_SHOW_SOURCE_LOCATION
+#define warn_print(...) warn_print_(__LINE__, __FILE__, __VA_ARGS__)
+#else
+#define warn_print warn_print_
+#endif
+
static void *err_malloc(size_t size) {
if (size == 0) return NULL;
void *ret = malloc(size);
diff --git a/package.c b/package.c
index 260c9d0..97d0007 100644
--- a/package.c
+++ b/package.c
@@ -11,18 +11,40 @@ static void exptr_create(Exporter *exptr, FILE *out) {
static void export_u8(Exporter *ex, U8 u8) {
write_u8(ex->out, u8);
}
-
+static void export_i8(Exporter *ex, I8 i8) {
+ write_i8(ex->out, i8);
+}
static void export_u16(Exporter *ex, U16 u16) {
write_u16(ex->out, u16);
}
-
+static void export_i16(Exporter *ex, I16 i16) {
+ write_i16(ex->out, i16);
+}
static void export_u32(Exporter *ex, U32 u32) {
write_u32(ex->out, u32);
}
-
+static void export_i32(Exporter *ex, I32 i32) {
+ write_i32(ex->out, i32);
+}
static void export_u64(Exporter *ex, U64 u64) {
write_u64(ex->out, u64);
}
+static void export_i64(Exporter *ex, I64 i64) {
+ write_i64(ex->out, i64);
+}
+static void export_f32(Exporter *ex, F32 f32) {
+ write_f32(ex->out, f32);
+}
+static void export_f64(Exporter *ex, F64 f64) {
+ write_f64(ex->out, f64);
+}
+static void export_bool(Exporter *ex, bool b) {
+ write_bool(ex->out, b);
+}
+static void export_char(Exporter *ex, char c) {
+ write_char(ex->out, c);
+}
+
static void export_location(Exporter *ex, Location where) {
if (ex->export_locations) {
@@ -43,6 +65,22 @@ static bool export_val(Exporter *ex, Value val, Type *type, Location where) {
export_type(ex, type);
switch (type->kind) {
case TYPE_VOID: break;
+ case TYPE_BUILTIN:
+ switch (type->builtin) {
+ case BUILTIN_I8: export_i8(ex, val.i8); break;
+ case BUILTIN_U8: export_u8(ex, val.u8); break;
+ case BUILTIN_I16: export_i16(ex, val.i16); break;
+ case BUILTIN_U16: export_u16(ex, val.u16); break;
+ case BUILTIN_I32: export_i32(ex, val.i32); break;
+ case BUILTIN_U32: export_u32(ex, val.u32); break;
+ case BUILTIN_I64: export_i64(ex, val.i64); break;
+ case BUILTIN_U64: export_u64(ex, val.u64); break;
+ case BUILTIN_F32: export_f32(ex, val.f32); break;
+ case BUILTIN_F64: export_f64(ex, val.f64); break;
+ case BUILTIN_BOOL: export_bool(ex, val.boolv); break;
+ case BUILTIN_CHAR: export_char(ex, val.charv); break;
+ }
+ break;
case TYPE_TYPE:
export_type(ex, val.type);
break;
diff --git a/parse.c b/parse.c
index 60298de..47dc8e9 100644
--- a/parse.c
+++ b/parse.c
@@ -97,6 +97,8 @@ static bool type_builtin_is_signed(BuiltinType b) {
case BUILTIN_I16:
case BUILTIN_I32:
case BUILTIN_I64:
+ case BUILTIN_F32:
+ case BUILTIN_F64:
return true;
default: return false;
}
diff --git a/test.toc b/test.toc
index ace8f11..1c2de62 100644
--- a/test.toc
+++ b/test.toc
@@ -1,2 +1,2 @@
-#export foo ::= 7;
+#export foo :: f64 = 0.07321;
asdf, dsajkhf, sadjkfh ::= 5;