diff options
-rw-r--r-- | arith.c | 185 | ||||
-rw-r--r-- | buf.c | 8 | ||||
-rw-r--r-- | chksum.c | 4 | ||||
-rwxr-xr-x | configure | 21 | ||||
-rw-r--r-- | ffi.c | 16 | ||||
-rw-r--r-- | hash.c | 13 | ||||
-rw-r--r-- | lib.c | 20 | ||||
-rw-r--r-- | lib.h | 154 | ||||
-rw-r--r-- | stream.c | 2 |
9 files changed, 347 insertions, 76 deletions
@@ -189,7 +189,14 @@ val normalize(val bignum) ucnum c_unum(val num, val self) { switch (type(num)) { - case CHR: case NUM: + case CHR: + { + cnum n = c_ch(num); + if (n >= 0) + return n; + } + goto range; + case NUM: { cnum n = c_n(num); if (n >= 0) @@ -227,7 +234,9 @@ val unum(ucnum u) dbl_cnum c_dbl_num(val n) { switch (type(n)) { - case CHR: case NUM: + case CHR: + return c_ch(n); + case NUM: return c_n(n); case BGNUM: if (mp_in_double_intptr_range(mp(n))) { @@ -245,7 +254,14 @@ dbl_cnum c_dbl_num(val n) dbl_ucnum c_dbl_unum(val n) { switch (type(n)) { - case CHR: case NUM: + case CHR: + { + dbl_cnum cn = c_ch(n); + if (cn >= 0) + return cn; + break; + } + case NUM: { dbl_cnum cn = c_n(n); if (cn >= 0) @@ -656,7 +672,7 @@ tail: break; case TAG_PAIR(TAG_CHR, TAG_NUM): { - wchar_t a = c_chr(anum); + wchar_t a = c_ch(anum); cnum b = c_n(bnum); cnum sum = a + b; @@ -667,7 +683,7 @@ tail: case TAG_PAIR(TAG_NUM, TAG_CHR): { cnum a = c_n(anum); - wchar_t b = c_chr(bnum); + wchar_t b = c_ch(bnum); cnum sum = a + b; if (sum < 0 || sum > 0x10FFFF) @@ -696,9 +712,18 @@ val minus(val anum, val bnum) tail: switch (TAG_PAIR(tag(anum), tag(bnum))) { - case TAG_PAIR(TAG_NUM, TAG_NUM): case TAG_PAIR(TAG_CHR, TAG_CHR): { + cnum a = c_ch(anum); + cnum b = c_ch(bnum); + cnum sum = a - b; + + if (sum < NUM_MIN || sum > NUM_MAX) + return bignum(sum); + return num_fast(sum); + } + case TAG_PAIR(TAG_NUM, TAG_NUM): + { cnum a = c_n(anum); cnum b = c_n(bnum); cnum sum = a - b; @@ -828,7 +853,7 @@ tail: break; case TAG_PAIR(TAG_CHR, TAG_NUM): { - wchar_t a = c_chr(anum); + wchar_t a = c_ch(anum); cnum b = c_n(bnum); cnum sum = a - b; @@ -911,7 +936,7 @@ static val signum(val anum) return if3(mp_isneg(mp(anum)), negone, one); case FLNUM: { - double a = anum->fl.n; + double a = c_f(anum); return flo(if3(a > 0, 1.0, if3(a < 0, -1.0, 0.0))); } case NUM: @@ -1967,10 +1992,13 @@ val gt(val anum, val bnum) tail: switch (TYPE_PAIR(type(anum), type(bnum))) { case TYPE_PAIR(NUM, NUM): + return c_n(anum) > c_n(bnum) ? t : nil; case TYPE_PAIR(CHR, CHR): + return c_ch(anum) > c_ch(bnum) ? t : nil; case TYPE_PAIR(NUM, CHR): + return c_n(anum) > c_ch(bnum) ? t : nil; case TYPE_PAIR(CHR, NUM): - return c_n(anum) > c_n(bnum) ? t : nil; + return c_ch(anum) > c_n(bnum) ? t : nil; case TYPE_PAIR(NUM, BGNUM): case TYPE_PAIR(CHR, BGNUM): return mp_cmp_z(mp(bnum)) == MP_LT ? t : nil; @@ -1980,11 +2008,13 @@ tail: case TYPE_PAIR(BGNUM, BGNUM): return mp_cmp(mp(anum), mp(bnum)) == MP_GT ? t : nil; case TYPE_PAIR(NUM, FLNUM): - case TYPE_PAIR(CHR, FLNUM): return c_n(anum) > c_flo(bnum, self) ? t : nil; + case TYPE_PAIR(CHR, FLNUM): + return c_ch(anum) > c_flo(bnum, self) ? t : nil; case TYPE_PAIR(FLNUM, NUM): - case TYPE_PAIR(FLNUM, CHR): return c_flo(anum, self) > c_n(bnum) ? t : nil; + case TYPE_PAIR(FLNUM, CHR): + return c_flo(anum, self) > c_ch(bnum) ? t : nil; case TYPE_PAIR(FLNUM, FLNUM): return c_flo(anum, self) > c_flo(bnum, self) ? t : nil; case TYPE_PAIR(FLNUM, BGNUM): @@ -2030,10 +2060,13 @@ val lt(val anum, val bnum) tail: switch (TYPE_PAIR(type(anum), type(bnum))) { case TYPE_PAIR(NUM, NUM): + return c_n(anum) < c_n(bnum) ? t : nil; case TYPE_PAIR(CHR, CHR): + return c_ch(anum) < c_ch(bnum) ? t : nil; case TYPE_PAIR(NUM, CHR): + return c_n(anum) < c_ch(bnum) ? t : nil; case TYPE_PAIR(CHR, NUM): - return c_n(anum) < c_n(bnum) ? t : nil; + return c_ch(anum) < c_n(bnum) ? t : nil; case TYPE_PAIR(NUM, BGNUM): case TYPE_PAIR(CHR, BGNUM): return mp_cmp_z(mp(bnum)) == MP_GT ? t : nil; @@ -2043,11 +2076,13 @@ tail: case TYPE_PAIR(BGNUM, BGNUM): return mp_cmp(mp(anum), mp(bnum)) == MP_LT ? t : nil; case TYPE_PAIR(NUM, FLNUM): - case TYPE_PAIR(CHR, FLNUM): return c_n(anum) < c_flo(bnum, self) ? t : nil; + case TYPE_PAIR(CHR, FLNUM): + return c_ch(anum) < c_flo(bnum, self) ? t : nil; case TYPE_PAIR(FLNUM, NUM): - case TYPE_PAIR(FLNUM, CHR): return c_flo(anum, self) < c_n(bnum) ? t : nil; + case TYPE_PAIR(FLNUM, CHR): + return c_flo(anum, self) < c_ch(bnum) ? t : nil; case TYPE_PAIR(FLNUM, FLNUM): return c_flo(anum, self) < c_flo(bnum, self) ? t : nil; case TYPE_PAIR(FLNUM, BGNUM): @@ -2093,10 +2128,13 @@ val ge(val anum, val bnum) tail: switch (TYPE_PAIR(type(anum), type(bnum))) { case TYPE_PAIR(NUM, NUM): + return c_n(anum) >= c_n(bnum) ? t : nil; case TYPE_PAIR(CHR, CHR): + return c_ch(anum) >= c_ch(bnum) ? t : nil; case TYPE_PAIR(NUM, CHR): + return c_n(anum) >= c_ch(bnum) ? t : nil; case TYPE_PAIR(CHR, NUM): - return c_n(anum) >= c_n(bnum) ? t : nil; + return c_ch(anum) >= c_n(bnum) ? t : nil; case TYPE_PAIR(NUM, BGNUM): case TYPE_PAIR(CHR, BGNUM): return mp_cmp_z(mp(bnum)) == MP_LT ? t : nil; @@ -2111,11 +2149,13 @@ tail: return nil; } case TYPE_PAIR(NUM, FLNUM): - case TYPE_PAIR(CHR, FLNUM): return c_n(anum) >= c_flo(bnum, self) ? t : nil; + case TYPE_PAIR(CHR, FLNUM): + return c_ch(anum) >= c_flo(bnum, self) ? t : nil; case TYPE_PAIR(FLNUM, NUM): - case TYPE_PAIR(FLNUM, CHR): return c_flo(anum, self) >= c_n(bnum) ? t : nil; + case TYPE_PAIR(FLNUM, CHR): + return c_flo(anum, self) >= c_ch(bnum) ? t : nil; case TYPE_PAIR(FLNUM, FLNUM): return c_flo(anum, self) >= c_flo(bnum, self) ? t : nil; case TYPE_PAIR(FLNUM, BGNUM): @@ -2161,10 +2201,13 @@ val le(val anum, val bnum) tail: switch (TYPE_PAIR(type(anum), type(bnum))) { case TYPE_PAIR(NUM, NUM): + return c_n(anum) <= c_n(bnum) ? t : nil; case TYPE_PAIR(CHR, CHR): + return c_ch(anum) <= c_ch(bnum) ? t : nil; case TYPE_PAIR(NUM, CHR): + return c_n(anum) <= c_ch(bnum) ? t : nil; case TYPE_PAIR(CHR, NUM): - return c_n(anum) <= c_n(bnum) ? t : nil; + return c_ch(anum) <= c_n(bnum) ? t : nil; case TYPE_PAIR(NUM, BGNUM): case TYPE_PAIR(CHR, BGNUM): return mp_cmp_z(mp(bnum)) == MP_GT ? t : nil; @@ -2179,11 +2222,13 @@ tail: return nil; } case TYPE_PAIR(NUM, FLNUM): - case TYPE_PAIR(CHR, FLNUM): return c_n(anum) <= c_flo(bnum, self) ? t : nil; + case TYPE_PAIR(CHR, FLNUM): + return c_ch(anum) <= c_flo(bnum, self) ? t : nil; case TYPE_PAIR(FLNUM, NUM): - case TYPE_PAIR(FLNUM, CHR): return c_flo(anum, self) <= c_n(bnum) ? t : nil; + case TYPE_PAIR(FLNUM, CHR): + return c_flo(anum, self) <= c_ch(bnum) ? t : nil; case TYPE_PAIR(FLNUM, FLNUM): return c_flo(anum, self) <= c_flo(bnum, self) ? t : nil; case TYPE_PAIR(FLNUM, BGNUM): @@ -2259,10 +2304,13 @@ val numeq(val anum, val bnum) tail: switch (TYPE_PAIR(type(anum), type(bnum))) { case TYPE_PAIR(NUM, NUM): + return c_n(anum) == c_n(bnum) ? t : nil; case TYPE_PAIR(CHR, CHR): + return c_ch(anum) == c_ch(bnum) ? t : nil; case TYPE_PAIR(NUM, CHR): + return c_n(anum) == c_ch(bnum) ? t : nil; case TYPE_PAIR(CHR, NUM): - return c_n(anum) == c_n(bnum) ? t : nil; + return c_ch(anum) == c_n(bnum) ? t : nil; case TYPE_PAIR(NUM, BGNUM): case TYPE_PAIR(CHR, BGNUM): return mp_cmp_z(mp(bnum)) == MP_EQ ? t : nil; @@ -2272,11 +2320,13 @@ tail: case TYPE_PAIR(BGNUM, BGNUM): return mp_cmp(mp(anum), mp(bnum)) == MP_EQ ? t : nil; case TYPE_PAIR(NUM, FLNUM): - case TYPE_PAIR(CHR, FLNUM): return c_n(anum) == c_flo(bnum, self) ? t : nil; + case TYPE_PAIR(CHR, FLNUM): + return c_ch(anum) == c_flo(bnum, self) ? t : nil; case TYPE_PAIR(FLNUM, NUM): - case TYPE_PAIR(FLNUM, CHR): return c_flo(anum, self) == c_n(bnum) ? t : nil; + case TYPE_PAIR(FLNUM, CHR): + return c_flo(anum, self) == c_ch(bnum) ? t : nil; case TYPE_PAIR(FLNUM, FLNUM): return c_flo(anum, self) == c_flo(bnum, self) ? t : nil; case TYPE_PAIR(FLNUM, BGNUM): @@ -3074,9 +3124,14 @@ val logand(val a, val b) switch (TYPE_PAIR(type(a), type(b))) { case TYPE_PAIR(NUM, CHR): - case TYPE_PAIR(CHR, NUM): { cnum ac = c_n(a); + cnum bc = c_ch(b); + return chr(ac & bc); + } + case TYPE_PAIR(CHR, NUM): + { + cnum ac = c_ch(a); cnum bc = c_n(b); return chr(ac & bc); } @@ -3125,9 +3180,14 @@ val logior(val a, val b) switch (TYPE_PAIR(type(a), type(b))) { case TYPE_PAIR(NUM, CHR): - case TYPE_PAIR(CHR, NUM): { cnum ac = c_n(a); + cnum bc = c_ch(b); + return chr(ac | bc); + } + case TYPE_PAIR(CHR, NUM): + { + cnum ac = c_ch(a); cnum bc = c_n(b); return chr(ac | bc); } @@ -3176,9 +3236,14 @@ val logxor(val a, val b) switch (TYPE_PAIR(type(a), type(b))) { case TYPE_PAIR(NUM, CHR): - case TYPE_PAIR(CHR, NUM): { cnum ac = c_n(a); + cnum bc = c_ch(b); + return chr(ac ^ bc); + } + case TYPE_PAIR(CHR, NUM): + { + cnum ac = c_ch(a); cnum bc = c_n(b); return chr(ac ^ bc); } @@ -3229,11 +3294,18 @@ val logxor_old(val a, val b) switch (TYPE_PAIR(type(a), type(b))) { case TYPE_PAIR(NUM, CHR): - case TYPE_PAIR(CHR, NUM): if (a == b) { return a; } else { cnum ac = c_n(a); + cnum bc = c_ch(b); + return chr(ac ^ bc); + } + case TYPE_PAIR(CHR, NUM): + if (a == b) { + return a; + } else { + cnum ac = c_ch(a); cnum bc = c_n(b); return chr(ac ^ bc); } @@ -3556,13 +3628,19 @@ val bit(val a, val bit) switch (ta) { case NUM: - case CHR: { cnum an = c_n(a); if (bn < (SIZEOF_PTR * CHAR_BIT)) return (an & (convert(cnum, 1) << bn)) ? t : nil; return an < 0 ? t : nil; } + case CHR: + { + cnum an = c_ch(a); + if (bn < (SIZEOF_PTR * CHAR_BIT)) + return (an & (convert(cnum, 1) << bn)) ? t : nil; + return an < 0 ? t : nil; + } case BGNUM: { mpe = mp_bit(mp(a), bn); @@ -3614,7 +3692,6 @@ val bitset(val n) switch (type(n)) { case NUM: - case CHR: { cnum c = c_n(n); ucnum d = c; @@ -3629,6 +3706,21 @@ val bitset(val n) return out; } + case CHR: + { + cnum c = c_ch(n); + ucnum d = c; + int p = 0; + + if (c < 0) + d = ~d; + + for (; d; d >>= 1, p++) + if (d & 1) + ptail = list_collect(ptail, num_fast(p)); + + return out; + } case BGNUM: { mp_int *mn = mp(n); @@ -3672,8 +3764,9 @@ val logcount(val n) val self = logcount_s; switch (type(n)) { - case NUM: case CHR: + return logcount(num_fast(c_ch(n))); + case NUM: { int_ptr_t c = c_n(n); uint_ptr_t d = c; @@ -3835,7 +3928,7 @@ val tofloat(val obj) return flo_int(obj); case TAG_CHR: { - cnum ch = c_n(obj); + cnum ch = c_ch(obj); if (ch >= '0' && ch <= '9') return flo(ch - '0'); return nil; @@ -3872,7 +3965,7 @@ val toint(val obj, val base) return int_str(obj, base); case TAG_CHR: { - cnum ch = c_n(obj); + cnum ch = c_ch(obj); if (ch >= '0' && ch <= '9') return num(ch - '0'); @@ -3928,6 +4021,7 @@ val width(val obj) switch (type(obj)) { case CHR: + return width(num_fast(c_ch(obj))); case NUM: { cnum n = c_n(obj); @@ -4128,7 +4222,9 @@ val num(cnum n) cnum c_num(val n, val self) { switch (type(n)) { - case CHR: case NUM: + case CHR: + return c_ch(n); + case NUM: return c_n(n); case BGNUM: if (mp_in_intptr_range(mp(n))) { @@ -4146,7 +4242,9 @@ cnum c_num(val n, val self) cnum c_fixnum(val num, val self) { switch (type(num)) { - case CHR: case NUM: + case CHR: + return c_ch(num); + case NUM: return c_n(num); default: type_mismatch(lit("~a: ~s is not fixnum integer or character"), @@ -4175,17 +4273,28 @@ val flo(double n) if (bad_float(n)) { uw_throw(numeric_error_s, lit("out-of-range floating-point result")); } else { +#if CONFIG_NAN_BOXING + ucnum u = *(ucnum *) &n + NAN_FLNUM_DELTA; + return coerce(val, u); +#else val obj = make_obj(); obj->fl.type = FLNUM; obj->fl.n = n; return obj; +#endif } } double c_flo(val num, val self) { +#if CONFIG_NAN_BOXING + if (is_flo(num)) + return c_f(num); + throw_mismatch(self, num, FLNUM); +#else type_check(self, num, FLNUM); return num->fl.n; +#endif } val fixnump(val num) @@ -4200,7 +4309,7 @@ val bignump(val num) val integerp(val num) { - switch (tag(num)) { + switch (tag_ex(num)) { case TAG_NUM: return t; case TAG_PTR: @@ -4221,9 +4330,13 @@ val floatp(val num) val numberp(val num) { - switch (tag(num)) { + switch (tag_ex(num)) { case TAG_NUM: return t; +#if CONFIG_NAN_BOXING + case TAG_FLNUM: + return t; +#endif case TAG_PTR: if (num == nil) return nil; @@ -1150,7 +1150,9 @@ static val buf_int(val num) val self = lit("buf-int"); switch (type(num)) { - case NUM: case CHR: + case CHR: + return buf_int(num_fast(c_ch(num))); + case NUM: num = bignum(c_num(num, self)); /* fallthrough */ case BGNUM: @@ -1180,7 +1182,9 @@ static val buf_uint(val num) val self = lit("buf-uint"); switch (type(num)) { - case NUM: case CHR: + case CHR: + return buf_uint(num_fast(c_ch(num))); + case NUM: num = bignum(c_num(num, self)); /* fallthrough */ case BGNUM: @@ -212,7 +212,7 @@ val sha256_hash(val ctx, val obj) sha256_szmax_upd(ps256, obj->b.data, c_unum(obj->b.len, self)); break; case CHR: - utf8_encode(c_chr(obj), sha256_utf8_byte_callback, coerce(mem_t *, ps256)); + utf8_encode(c_ch(obj), sha256_utf8_byte_callback, coerce(mem_t *, ps256)); break; case NUM: { @@ -476,7 +476,7 @@ val md5_hash(val ctx, val obj) md5_szmax_upd(pmd5, obj->b.data, c_unum(obj->b.len, self)); break; case CHR: - utf8_encode(c_chr(obj), md5_utf8_byte_callback, coerce(mem_t *, pmd5)); + utf8_encode(c_ch(obj), md5_utf8_byte_callback, coerce(mem_t *, pmd5)); break; case NUM: { @@ -1586,7 +1586,8 @@ fi if ! [ $nan_boxing_given ] ; then printf "Checking whether to use NaN boxing ... " - if [ $SIZEOF_PTR -eq 8 ] ; then + # too experimental: disabled + if false && [ $SIZEOF_PTR -eq 8 ] ; then nan_boxing=y printf "yes\n" else @@ -1601,6 +1602,24 @@ if [ -n "$nan_boxing" ] ; then printf "#define CONFIG_NAN_BOXING 1\n" >> config.h fi +if [ -n "$nan_boxing" ] ; then + printf "Checking how to disable strict aliasing warnings ... " + + cat > conftest.c <<! +int main(void) +{ + return 0; +} +! + + if conftest EXTRA_FLAGS=-Wno-strict-aliasing ; then + printf -- "-Wno-strict-aliasing\n" + diag_flags="$diag_flags -Wno-strict-aliasing" + else + printf "unknown\n" + fi +fi + printf "Checking for intmax_t ... " cat > conftest.c <<! #include <inttypes.h> @@ -879,8 +879,10 @@ static void ffi_float_put(struct txr_ffi_type *tft, val n, mem_t *dst, val self) switch (type(n)) { case NUM: + v = c_n(n); + break; case CHR: - v = c_num(n, self); + v = c_ch(n); break; case BGNUM: n = int_flo(n); @@ -918,8 +920,10 @@ static void ffi_double_put(struct txr_ffi_type *tft, val n, mem_t *dst, switch (type(n)) { case NUM: + v = c_n(n); + break; case CHR: - v = c_num(n, self); + v = c_ch(n); break; case BGNUM: n = int_flo(n); @@ -6618,7 +6622,9 @@ val carray_uint(val num, val eltype_in) carray_elem_check(tft, self); switch (type(num)) { - case NUM: case CHR: + case CHR: + return carray_uint(num_fast(c_ch(num)), eltype); + case NUM: num = bignum(c_num(num, self)); /* fallthrough */ case BGNUM: @@ -6653,7 +6659,9 @@ val carray_int(val num, val eltype_in) carray_elem_check(tft, self); switch (type(num)) { - case NUM: case CHR: + case CHR: + return carray_int(num_fast(c_ch(num)), eltype); + case NUM: num = bignum(c_num(num, self)); /* fallthrough */ case BGNUM: @@ -317,6 +317,7 @@ ucnum equal_hash(val obj, int *count, ucnum seed) case STR: return hash_c_str(obj->st.str, seed, count); case CHR: + return c_ch(obj); case NUM: return c_u(obj); case SYM: @@ -358,7 +359,7 @@ ucnum equal_hash(val obj, int *count, ucnum seed) case BGNUM: return mp_hash(mp(obj)) * if3(seed, seed, 1); case FLNUM: - return hash_double(obj->fl.n) * if3(seed, seed, 1); + return hash_double(c_f(obj)) * if3(seed, seed, 1); case COBJ: case CPTR: if (obj->co.ops->equalsub) { @@ -394,7 +395,7 @@ static ucnum eql_hash(val obj, int *count) case BGNUM: return mp_hash(mp(obj)); case FLNUM: - return hash_double(obj->fl.n); + return hash_double(c_f(obj)); case RNG: return eql_hash(obj->rn.from, count) + 2 * eql_hash(obj->rn.to, count); default: @@ -406,6 +407,7 @@ static ucnum eql_hash(val obj, int *count) } } case TAG_CHR: + return c_ch(obj); case TAG_NUM: return c_u(obj); case TAG_LIT: @@ -422,7 +424,7 @@ static ucnum eql_hash(val obj, int *count) static ucnum eq_hash(val obj) { - switch (tag(obj)) { + switch (tag_ex(obj)) { case TAG_PTR: switch (CHAR_BIT * sizeof (mem_t *)) { case 32: @@ -431,6 +433,7 @@ static ucnum eq_hash(val obj) return coerce(ucnum, obj) >> 5; } case TAG_CHR: + return c_ch(obj); case TAG_NUM: return c_u(obj); case TAG_LIT: @@ -440,6 +443,10 @@ static ucnum eq_hash(val obj) case 64: default: return coerce(ucnum, obj) >> 3; } +#if CONFIG_NAN_BOXING + case TAG_FLNUM: + return coerce(ucnum, obj); +#endif } /* notreached */ abort(); @@ -153,6 +153,7 @@ const seq_kind_t seq_kind_tab[MAXTYPE+1] = { SEQ_NOTSEQ, /* NUM */ SEQ_NOTSEQ, /* CHR */ SEQ_VECLIKE, /* LIT */ + SEQ_NOTSEQ, /* FLNUM */ SEQ_LISTLIKE, /* CONS */ SEQ_VECLIKE, /* STR */ SEQ_NOTSEQ, /* SYM */ @@ -165,7 +166,6 @@ const seq_kind_t seq_kind_tab[MAXTYPE+1] = { SEQ_NOTSEQ, /* CPTR */ SEQ_NOTSEQ, /* ENV */ SEQ_NOTSEQ, /* BGNUM */ - SEQ_NOTSEQ, /* FLNUM */ SEQ_NOTSEQ, /* RNG */ SEQ_VECLIKE, /* BUF */ SEQ_NOTSEQ, /* TNOD */ @@ -811,7 +811,7 @@ val seq_geti(seq_iter_t *it) return v; } -static void seq_iter_rewind(seq_iter_t *it, val self) +static void seq_iter_rewind(seq_iter_t *it) { switch (it->inf.type) { case RNG: @@ -820,10 +820,10 @@ static void seq_iter_rewind(seq_iter_t *it, val self) switch (type(rf)) { case NUM: - it->ui.cn = c_num(rf, self); + it->ui.cn = c_n(rf); break; case CHR: - it->ui.cn = c_chr(rf); + it->ui.cn = c_ch(rf); break; case BGNUM: it->ui.vn = rf; @@ -1241,7 +1241,7 @@ val iter_more(val iter) case NIL: return nil; case CHR: - return if2(c_chr(iter) <= 0x10FFFF, t); + return if2(c_ch(iter) <= 0x10FFFF, t); case NUM: case BGNUM: return t; @@ -4180,7 +4180,7 @@ val equal(val left, val right) break; case FLNUM: if (type(right) == FLNUM) { - if (left->fl.n == right->fl.n) + if (c_f(left) == c_f(right)) return t; return nil; } @@ -5096,7 +5096,7 @@ val string_get_code(val str) val stringp(val str) { - if (str) switch (tag(str)) { + if (str) switch (tag_ex(str)) { case TAG_LIT: return t; case TAG_PTR: @@ -12216,7 +12216,7 @@ val diff(val seq1, val seq2, val testfun, val keyfun) val el2; int found = 0; - seq_iter_rewind(&si2, self); + seq_iter_rewind(&si2); while (seq_get(&si2, &el2)) { val el2_key = funcall1(keyfun, el2); @@ -12322,7 +12322,7 @@ val isec(val seq1, val seq2, val testfun, val keyfun) val el1_key = funcall1(keyfun, el1); val el2; - seq_iter_rewind(&si2, self); + seq_iter_rewind(&si2); while (seq_get(&si2, &el2)) { val el2_key = funcall1(keyfun, el2); @@ -12354,7 +12354,7 @@ val isecp(val seq1, val seq2, val testfun, val keyfun) val el1_key = funcall1(keyfun, el1); val el2; - seq_iter_rewind(&si2, self); + seq_iter_rewind(&si2); while (seq_get(&si2, &el2)) { val el2_key = funcall1(keyfun, el2); @@ -52,18 +52,42 @@ typedef double_uintptr_t dbl_ucnum; #define FLEX_ARRAY 1 #endif -#define TAG_SHIFT 2 -#define TAG_MASK ((convert(cnum, 1) << TAG_SHIFT) - 1) +#define PTR_BIT (SIZEOF_PTR * CHAR_BIT) + #define TAG_PTR 0 #define TAG_NUM 1 #define TAG_CHR 2 #define TAG_LIT 3 -#define NUM_MAX (INT_PTR_MAX/4) -#define NUM_MIN (INT_PTR_MIN/4) -#define PTR_BIT (SIZEOF_PTR * CHAR_BIT) +#if CONFIG_NAN_BOXING + +#define TAG_FLNUM 4 /* pseudo-tag */ +#define TAG_WIDTH 2 +#define TAG_PAIR(A, B) ((A) << TAG_WIDTH | (B)) + +#define NAN_TAG_BIT 14 +#define NAN_TAG_MASK 0xFFFC000000000000U +#define TAG_BIGMASK 0xFFFF000000000000U +#define TAG_BIGSHIFT 48 + +#define NAN_FLNUM_DELTA 0x0004000000000000U + +#define NUM_MAX (INT_PTR_MAX >> NAN_TAG_BIT) +#define NUM_MIN (INT_PTR_MIN >> NAN_TAG_BIT) +#define NUM_BIT (PTR_BIT - NAN_TAG_BIT) + +#else + +#define TAG_SHIFT 2 +#define TAG_MASK ((convert(cnum, 1) << TAG_SHIFT) - 1) +#define TAG_PAIR(A, B) ((A) << TAG_SHIFT | (B)) + +#define NUM_MAX (INT_PTR_MAX >> TAG_SHIFT) +#define NUM_MIN (INT_PTR_MIN >> TAG_SHIFT) #define NUM_BIT (PTR_BIT - TAG_SHIFT) +#endif + #ifdef __GNUC__ #define NORETURN __attribute__((noreturn)) #define NOINLINE __attribute__((noinline)) @@ -73,15 +97,14 @@ typedef double_uintptr_t dbl_ucnum; #endif typedef enum type { - NIL = TAG_PTR, NUM = TAG_NUM, CHR = TAG_CHR, LIT = TAG_LIT, CONS, - STR, SYM, PKG, FUN, VEC, LCONS, LSTR, COBJ, CPTR, ENV, - BGNUM, FLNUM, RNG, BUF, TNOD, DARG, MAXTYPE = DARG + NIL = TAG_PTR, NUM = TAG_NUM, CHR = TAG_CHR, LIT = TAG_LIT, FLNUM, + CONS, STR, SYM, PKG, FUN, VEC, LCONS, LSTR, COBJ, CPTR, ENV, + BGNUM, RNG, BUF, TNOD, DARG, MAXTYPE = DARG /* If extending, check TYPE_SHIFT and all ocurrences of MAX_TYPE */ } type_t; #define TYPE_SHIFT 5 #define TYPE_PAIR(A, B) ((A) << TYPE_SHIFT | (B)) -#define TAG_PAIR(A, B) ((A) << TAG_SHIFT | (B)) typedef enum functype { @@ -315,10 +338,12 @@ struct bignum { mp_int mp; }; +#if !CONFIG_NAN_BOXING struct flonum { obj_common; double n; }; +#endif struct range { obj_common; @@ -353,7 +378,9 @@ union obj { struct cptr cp; struct env e; struct bignum bn; +#if !CONFIG_NAN_BOXING struct flonum fl; +#endif struct range rn; struct buf b; struct tnod tn; @@ -438,15 +465,54 @@ extern const seq_kind_t seq_kind_tab[MAXTYPE+1]; #define SEQ_KIND_PAIR(A, B) ((A) << 3 | (B)) +#if CONFIG_NAN_BOXING + +INLINE cnum tag(val obj) +{ + ucnum word = coerce(ucnum, obj) >> TAG_BIGSHIFT; + if (word <= TAG_LIT) + return word; + if ((word & (NAN_TAG_MASK >> TAG_BIGSHIFT)) == (NAN_TAG_MASK >> TAG_BIGSHIFT)) + return TAG_NUM; + return TAG_PTR; +} + +INLINE cnum tag_ex(val obj) +{ + ucnum word = coerce(ucnum, obj) >> TAG_BIGSHIFT; + if (word <= TAG_LIT) + return word; + if ((word & (NAN_TAG_MASK >> TAG_BIGSHIFT)) == (NAN_TAG_MASK >> TAG_BIGSHIFT)) + return TAG_NUM; + return TAG_FLNUM; +} + +INLINE int is_ptr(val obj) +{ + return obj && coerce(ucnum, obj) >> TAG_BIGSHIFT == TAG_PTR; +} + +INLINE int is_flo(val obj) +{ + ucnum nantag = coerce(ucnum, obj) & NAN_TAG_MASK; + return nantag != 0 && nantag != NAN_TAG_MASK; +} + +#else + INLINE cnum tag(val obj) { return coerce(cnum, obj) & TAG_MASK; } +INLINE cnum tag_ex(val obj) { return tag(obj); } INLINE int is_ptr(val obj) { return obj && tag(obj) == TAG_PTR; } + +#endif + INLINE int is_num(val obj) { return tag(obj) == TAG_NUM; } INLINE int is_chr(val obj) { return tag(obj) == TAG_CHR; } INLINE int is_lit(val obj) { return tag(obj) == TAG_LIT; } INLINE type_t type(val obj) { - cnum tg = tag(obj); + cnum tg = tag_ex(obj); return obj ? tg ? convert(type_t, tg) : obj->t.type @@ -455,7 +521,7 @@ INLINE type_t type(val obj) typedef struct wli wchli_t; -#if SIZEOF_WCHAR_T < 4 +#if SIZEOF_WCHAR_T < 4 && !CONFIG_NAN_BOXING #define wli_noex(lit) (coerce(const wchli_t *,\ convert(const wchar_t *,\ L"\0" L ## lit L"\0" + 1))) @@ -472,19 +538,31 @@ typedef struct wli wchli_t; INLINE val auto_str(const wchli_t *str) { +#if CONFIG_NAN_BOXING + return coerce(val, coerce(cnum, str) | + (coerce(cnum, TAG_LIT) << TAG_BIGSHIFT)); +#else return coerce(val, coerce(cnum, str) | TAG_LIT); +#endif } INLINE val static_str(const wchli_t *str) { +#if CONFIG_NAN_BOXING + return coerce(val, coerce(cnum, str) | + (coerce(cnum, TAG_LIT) << TAG_BIGSHIFT)); +#else return coerce(val, coerce(cnum, str) | TAG_LIT); +#endif } INLINE wchar_t *litptr(val obj) { -#if SIZEOF_WCHAR_T < 4 +#if SIZEOF_WCHAR_T < 4 && !CONFIG_NAN_BOXING wchar_t *ret = coerce(wchar_t *, (coerce(cnum, obj) & ~TAG_MASK)); return (*ret == 0) ? ret + 1 : ret; +#elif CONFIG_NAN_BOXING + return coerce(wchar_t *, coerce(cnum, obj) & ~TAG_BIGMASK); #else return coerce(wchar_t *, coerce(cnum, obj) & ~TAG_MASK); #endif @@ -492,7 +570,9 @@ INLINE wchar_t *litptr(val obj) INLINE val num_fast(cnum n) { -#if HAVE_UBSAN +#if CONFIG_NAN_BOXING + return coerce(val, n | NAN_TAG_MASK); +#elif HAVE_UBSAN return coerce(val, (n * (1 << TAG_SHIFT)) | TAG_NUM); #else return coerce(val, (n << TAG_SHIFT) | TAG_NUM); @@ -506,25 +586,60 @@ INLINE mp_int *mp(val bign) INLINE val chr(wchar_t ch) { +#if CONFIG_NAN_BOXING + return coerce(val, ch | convert(cnum, TAG_CHR) << TAG_BIGSHIFT); +#else return coerce(val, (convert(cnum, ch) << TAG_SHIFT) | TAG_CHR); +#endif +} + +INLINE cnum c_ch(val num) +{ +#if CONFIG_NAN_BOXING + return coerce(cnum, num) & ~TAG_BIGMASK; +#else + return coerce(cnum, num) >> TAG_SHIFT; +#endif } INLINE cnum c_n(val num) { +#if CONFIG_NAN_BOXING + cnum n = coerce(cnum, num) & ~NAN_TAG_MASK; + return n << NAN_TAG_BIT >> NAN_TAG_BIT; +#else return coerce(cnum, num) >> TAG_SHIFT; +#endif } INLINE ucnum c_u(val num) { +#if CONFIG_NAN_BOXING + return coerce(ucnum, num) & ~NAN_TAG_MASK; +#else return convert(ucnum, coerce(cnum, num) >> TAG_SHIFT); +#endif } -#if SIZEOF_WCHAR_T < 4 +INLINE double c_f(val num) +{ +#if CONFIG_NAN_BOXING + ucnum u = coerce(ucnum, num) - NAN_FLNUM_DELTA; + return *coerce(double *, &u); +#else + return num->fl.n; +#endif +} + +#if SIZEOF_WCHAR_T < 4 && !CONFIG_NAN_BOXING #define lit_noex(strlit) coerce(obj_t *,\ coerce(cnum, L"\0" L ## strlit L"\0" + 1) | \ TAG_LIT) +#elif CONFIG_NAN_BOXING +#define lit_noex(strlit) coerce(val, coerce(cnum, L ## strlit) | \ + (coerce(cnum, TAG_LIT) << TAG_BIGSHIFT)) #else -#define lit_noex(strlit) coerce(obj_t *, coerce(cnum, L ## strlit) | TAG_LIT) +#define lit_noex(strlit) coerce(val, coerce(cnum, L ## strlit) | TAG_LIT) #endif #define lit(strlit) lit_noex(strlit) @@ -610,7 +725,7 @@ val iter_more(val iter); val iter_item(val iter); val iter_step(val iter); val iter_reset(val iter, val obj); -val throw_mismatch(val self, val obj, type_t); +NORETURN val throw_mismatch(val self, val obj, type_t); INLINE val type_check(val self, val obj, type_t typecode) { if (type(obj) != typecode) @@ -1300,7 +1415,12 @@ INLINE val null(val v) { return v ? nil : t; } #define nilp(o) ((o) == nil) -#define nao coerce(obj_t *, 1 << TAG_SHIFT) /* "not an object" sentinel value. */ +/* "not an object" sentinel value. */ +#if CONFIG_NAN_BOXING +#define nao coerce(obj_t *, 1) +#else +#define nao coerce(obj_t *, 1 << TAG_SHIFT) +#endif #define missingp(v) ((v) == colon_k) @@ -3709,7 +3709,7 @@ val formatv(val stream_in, val fmtstr, struct args *al) uw_throwf(error_s, lit("~a: excessive precision: ~s"), self, num(precision), nao); - sprintf(num_buf, "%.*g", precision, obj->fl.n); + sprintf(num_buf, "%.*g", precision, c_f(obj)); #if CONFIG_LOCALE_TOLERANCE if (dec_point != '.') { |