Hexadecimal floats for "perfect values" 0h42f60000 == 123; use bit_cast in compiler

This commit is contained in:
gingerBill
2018-02-25 15:09:16 +00:00
parent 27b7dc336a
commit d247ba4751
9 changed files with 70 additions and 54 deletions
+1 -1
View File
@@ -346,7 +346,7 @@ void init_build_context(void) {
{
u16 x = 1;
bool big = !(*cast(u8 *)&x);
bool big = !bit_cast<u8>(x);
bc->ODIN_ENDIAN = big ? str_lit("big") : str_lit("little");
}
+2 -2
View File
@@ -1227,7 +1227,7 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
}
i64 i = v.value_integer;
u64 u = *cast(u64 *)&i;
u64 u = bit_cast<u64>(i);
i64 s = 8*type_size_of(c->allocator, type);
u64 umax = ~cast(u64)0ull;
if (s < 64) {
@@ -1336,7 +1336,7 @@ void check_is_expressible(Checker *c, Operand *o, Type *type) {
String str = {};
i64 i = o->value.value_integer;
if (is_type_unsigned(o->type)) {
str = u64_to_string(*cast(u64 *)&i, buf, gb_size_of(buf));
str = u64_to_string(bit_cast<u64>(i), buf, gb_size_of(buf));
} else {
str = i64_to_string(i, buf, gb_size_of(buf));
}
+1 -1
View File
@@ -262,7 +262,7 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) {
ExactValue v = exact_value_to_integer(rhs->value);
if (v.kind == ExactValue_Integer) {
i64 i = v.value_integer;
u64 u = *cast(u64 *)&i;
u64 u = bit_cast<u64>(i);
u64 umax = ~cast(u64)0ull;
if (lhs_bits < 64) {
umax = (1ull << cast(u64)lhs_bits) - 1ull;
+9
View File
@@ -12,6 +12,14 @@
#include <math.h>
template <typename U, typename V>
gb_inline U bit_cast(V &v) { return reinterpret_cast<U &>(v); }
template <typename U, typename V>
gb_inline U const &bit_cast(V const &v) { return reinterpret_cast<U const &>(v); }
gb_inline i64 align_formula(i64 size, i64 align) {
if (align > 0) {
i64 result = size + align-1;
@@ -164,6 +172,7 @@ u64 u64_from_string(String string) {
case 'd': base = 10; has_prefix = true; break;
case 'z': base = 12; has_prefix = true; break;
case 'x': base = 16; has_prefix = true; break;
case 'h': base = 16; has_prefix = true; break;
}
}
+23 -34
View File
@@ -156,39 +156,6 @@ f64 float_from_string(String string) {
i++;
}
#if 0
if (len-i > 2 &&
str[i] == '0' &&
str[i+1] == 'h') {
i += 2;
u8 *text = string.text;
isize len = string.len;
if (has_prefix) {
text += 2;
len -= 2;
}
u64 base = 16;
u64 result = {0};
for (isize i = 0; i < len; i++) {
Rune r = cast(Rune)text[i];
if (r == '_') {
continue;
}
u64 v = bit128__digit_value(r);
if (v >= base) {
break;
}
result *= base;
result += v;
}
return *cast(f64 *)&result;
}
#endif
f64 value = 0.0;
for (; i < len; i++) {
Rune r = cast(Rune)str[i];
@@ -255,7 +222,29 @@ f64 float_from_string(String string) {
}
ExactValue exact_value_float_from_string(String string) {
return exact_value_float(float_from_string(string));
if (string.len > 2 && string[0] == '0' && string[1] == 'h') {
isize digit_count = 0;
for (isize i = 2; i < string.len; i++) {
if (string[i] != '_') {
digit_count += 1;
}
}
u64 u = u64_from_string(string);
if (digit_count == 8) {
u32 x = cast(u32)u;
f32 f = bit_cast<f32>(x);
return exact_value_float(cast(f64)f);
} else if (digit_count == 16) {
f64 f = bit_cast<f64>(u);
return exact_value_float(f);
} else {
GB_PANIC("Invalid hexadecimal float, expected 8 or 16 digits, got %td", digit_count);
}
}
f64 f = float_from_string(string);
return exact_value_float(f);
}
+6 -6
View File
@@ -278,7 +278,7 @@ f64 u128_to_f64(u128 a) {
return -((cast(f64)h * 18446744073709551616.0) + cast(f64)l);
}
i128 u128_to_i128(u128 a) {
return *cast(i128 *)&a;
return bit_cast<i128>(a);
}
@@ -306,7 +306,7 @@ f64 i128_to_f64(i128 a) {
return -((cast(f64)h * 18446744073709551616.0) + cast(f64)l);
}
u128 i128_to_u128(i128 a) {
return *cast(u128 *)&a;
return bit_cast<u128>(a);
}
@@ -335,7 +335,7 @@ String i128_to_string(i128 a, char *out_buf, isize out_buf_len) {
a = i128_neg(a);
}
u128 v = *cast(u128 *)&a;
u128 v = bit_cast<u128>(a);
u128 b = u128_from_u64(10);;
while (u128_ge(v, b)) {
buf[--i] = gb__num_to_char_table[u128_to_i64(u128_mod(v, b))];
@@ -692,9 +692,9 @@ void i128_divide(i128 a, i128 b, i128 *quo_, i128 *rem_) {
irem = i128_from_i64(r);
} else if (a.hi > 0 || b.hi > 0) {
u128 q, r = {0};
u128_divide(*cast(u128 *)&a, *cast(u128 *)&b, &q, &r);
iquo = *cast(i128 *)&q;
irem = *cast(i128 *)&r;
u128_divide(bit_cast<u128>(a), bit_cast<u128>(b), &q, &r);
iquo = bit_cast<i128>(q);
irem = bit_cast<i128>(r);
} else if (i128_eq(b, I128_ZERO)) {
iquo = i128_from_u64(a.lo/b.lo);
} else {
+1 -1
View File
@@ -595,7 +595,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
case ExactValue_Float: {
GB_ASSERT_MSG(is_type_float(type), "%s", type_to_string(type));
type = core_type(type);
u64 u = *cast(u64*)&value.value_float;
u64 u = bit_cast<u64>(value.value_float);
switch (type->Basic.kind) {
case Basic_f32:
// IMPORTANT NOTE(bill): LLVM requires all floating point constants to be
+1 -1
View File
@@ -72,7 +72,7 @@ gb_inline HashKey hash_integer(u64 u) {
}
gb_inline HashKey hash_f64(f64 f) {
HashKey h = {HashKey_Default};
h.key = *cast(u64 *)&f;
h.key = bit_cast<u64>(f);
return h;
}
+26 -8
View File
@@ -254,7 +254,7 @@ void syntax_error_va(Token token, char *fmt, va_list va) {
LIT(token.pos.file), token.pos.line, token.pos.column,
gb_bprintf_va(fmt, va));
} else if (token.pos.line == 0) {
gb_printf_err("Error: %s\n", gb_bprintf_va(fmt, va));
gb_printf_err("Syntax Error: %s\n", gb_bprintf_va(fmt, va));
}
gb_mutex_unlock(&global_error_collector.mutex);
@@ -401,15 +401,15 @@ void tokenizer_err(Tokenizer *t, char *msg, ...) {
if (column < 1) {
column = 1;
}
gb_printf_err("%.*s(%td:%td) Syntax error: ", LIT(t->fullpath), t->line_count, column);
Token token = {};
token.pos.file = t->fullpath;
token.pos.line = t->line_count;
token.pos.column = column;
va_start(va, msg);
gb_printf_err_va(msg, va);
syntax_error_va(token, msg, va);
va_end(va);
gb_printf_err("\n");
t->error_count++;
}
@@ -577,14 +577,32 @@ Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
}
} /* else if (t->curr_rune == 'h') { // Hexadecimal Float
} else if (t->curr_rune == 'h') { // Hexadecimal Float
token.kind = Token_Float;
advance_to_next_rune(t);
scan_mantissa(t, 16);
if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
} else {
u8 *start = prev+2;
isize n = t->curr - start;
isize digit_count = 0;
for (isize i = 0; i < n; i++) {
if (start[i] != '_') {
digit_count += 1;
}
}
switch (digit_count) {
case 8:
case 16:
break;
default:
tokenizer_err(t, "Invalid hexadecimal float, expected 8 or 16 digits, got %td", digit_count);
break;
}
}
} */ else {
} else {
seen_decimal_point = false;
scan_mantissa(t, 10);