From 5c23113aa2631bd4d1ef71c4964bf32f7daf1010 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Fri, 27 Dec 2019 15:33:28 -0500 Subject: more work on exporting (floats), discovered bug --- binfile.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- err.c | 18 ++++++++++-- package.c | 44 +++++++++++++++++++++++++++-- parse.c | 2 ++ test.toc | 2 +- 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; -- cgit v1.2.3