Implement u128/i128 features; Add bits.odin

This commit is contained in:
Ginger Bill
2017-06-01 14:23:46 +01:00
parent fec6df65b3
commit 0d4945dc87
13 changed files with 497 additions and 303 deletions
+18 -2
View File
@@ -206,12 +206,20 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) {
return false;
}
for (isize i = 0; i < a->param_count; i++) {
Type *x = base_type(a->params->Tuple.variables[i]->type);
Type *y = base_type(b->params->Tuple.variables[i]->type);
Type *x = core_type(a->params->Tuple.variables[i]->type);
Type *y = core_type(b->params->Tuple.variables[i]->type);
if (is_type_pointer(x) && is_type_pointer(y)) {
continue;
}
if (is_type_integer(x) && is_type_integer(y)) {
GB_ASSERT(x->kind == Type_Basic);
GB_ASSERT(y->kind == Type_Basic);
if (x->Basic.size == y->Basic.size) {
continue;
}
}
if (!are_types_identical(x, y)) {
return false;
}
@@ -223,6 +231,14 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) {
continue;
}
if (is_type_integer(x) && is_type_integer(y)) {
GB_ASSERT(x->kind == Type_Basic);
GB_ASSERT(y->kind == Type_Basic);
if (x->Basic.size == y->Basic.size) {
continue;
}
}
if (!are_types_identical(x, y)) {
return false;
}
+3 -3
View File
@@ -2000,7 +2000,7 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
case Basic_i16:
case Basic_i32:
case Basic_i64:
// case Basic_i128:
case Basic_i128:
case Basic_int:
return i128_le(i128_neg(imax), i) && i128_le(i, i128_sub(imax, I128_ONE));
@@ -2008,7 +2008,7 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
case Basic_u16:
case Basic_u32:
case Basic_u64:
// case Basic_u128:
case Basic_u128:
case Basic_uint:
return !(u128_lt(u, U128_ZERO) || u128_gt(u, umax));
@@ -2338,7 +2338,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
}
i64 amount = i128_to_i64(y_val.value_integer);
if (amount > 64) {
if (amount > 128) {
gbString err_str = expr_to_string(y->expr);
error_node(node, "Shift amount too large: `%s`", err_str);
gb_string_free(err_str);
+8 -5
View File
@@ -6384,20 +6384,23 @@ gb_global char const gb__num_to_char_table[] =
gb_inline void gb_i64_to_str(i64 value, char *string, i32 base) {
char *buf = string;
b32 negative = false;
u64 v;
if (value < 0) {
negative = true;
value = -value;
}
if (value) {
while (value > 0) {
*buf++ = gb__num_to_char_table[value % base];
value /= base;
v = cast(u64)value;
if (v != 0) {
while (v > 0) {
*buf++ = gb__num_to_char_table[v % base];
v /= base;
}
} else {
*buf++ = '0';
}
if (negative)
if (negative) {
*buf++ = '-';
}
*buf = '\0';
gb_strrev(string);
}
+35 -35
View File
@@ -243,60 +243,44 @@ f64 i128_to_f64(i128 a) {
}
String u128_to_string(u128 a, char *out_buf, isize out_buf_len) {
String u128_to_string(u128 v, char *out_buf, isize out_buf_len) {
char buf[200] = {0};
isize i = 0;
isize i = gb_size_of(buf);
if (u128_ne(a, U128_ZERO)) {
u128 base = u128_from_u64(10);
while (u128_gt(a, U128_ZERO)) {
i64 digit = u128_to_i64(u128_mod(a, base));
buf[i++] = gb__num_to_char_table[digit];
a = u128_quo(a, base);
}
} else {
buf[i++] = '0';
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))];
v = u128_quo(v, b);
}
buf[--i] = gb__num_to_char_table[u128_to_i64(u128_mod(v, b))];
gb_reverse(buf, i, 1);
isize len = gb_min(i, out_buf_len);
gb_memcopy(out_buf, &buf[0], len);
isize len = gb_min(gb_size_of(buf)-i, out_buf_len);
gb_memcopy(out_buf, &buf[i], len);
return make_string(cast(u8 *)out_buf, len);
}
String i128_to_string(i128 a, char *out_buf, isize out_buf_len) {
char buf[200] = {0};
isize i = 0;
isize i = gb_size_of(buf);
bool negative = false;
if (i128_lt(a, I128_ZERO)) {
negative = true;
a = i128_neg(a);
}
if (i128_ne(a, I128_ZERO)) {
i128 base = i128_from_u64(10);
while (i128_gt(a, I128_ZERO)) {
i64 digit = i128_to_i64(i128_mod(a, base));
buf[i++] = gb__num_to_char_table[digit];
a = i128_quo(a, base);
}
} else {
buf[i++] = '0';
u128 v = *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))];
v = u128_quo(v, b);
}
buf[--i] = gb__num_to_char_table[u128_to_i64(u128_mod(v, b))];
if (negative) {
buf[i++] = '-';
buf[--i] = '-';
}
GB_ASSERT(i > 0);
for (isize j = 0; j < i/2; j++) {
char tmp = buf[j];
buf[j] = buf[i-1-j];
buf[i-1-j] = tmp;
}
isize len = gb_min(i, out_buf_len);
gb_memcopy(out_buf, &buf[0], len);
isize len = gb_min(gb_size_of(buf)-i, out_buf_len);
gb_memcopy(out_buf, &buf[i], len);
return make_string(cast(u8 *)out_buf, len);
}
@@ -571,6 +555,21 @@ i128 i128_mul(i128 a, i128 b) {
}
void i128_divide(i128 num, i128 den, i128 *quo, i128 *rem) {
// TODO(bill): Which one is correct?!
#if 0
i128 s = i128_shr(den, 127);
den = i128_sub(i128_xor(den, s), s);
s = i128_shr(num, 127);
den = i128_sub(i128_xor(num, s), s);
u128 n, r = {0};
u128_divide(*cast(u128 *)&num, *cast(u128 *)&den, &n, &r);
i128 ni = *cast(i128 *)&n;
i128 ri = *cast(i128 *)&r;
if (quo) *quo = i128_sub(i128_xor(ni, s), s);
if (rem) *rem = i128_sub(i128_xor(ri, s), s);
#else
if (i128_eq(den, I128_ZERO)) {
if (quo) *quo = i128_from_u64(num.lo/den.lo);
if (rem) *rem = I128_ZERO;
@@ -598,6 +597,7 @@ void i128_divide(i128 num, i128 den, i128 *quo, i128 *rem) {
if (quo) *quo = r;
if (rem) *rem = n;
}
#endif
}
i128 i128_quo(i128 a, i128 b) {
+22 -3
View File
@@ -2117,9 +2117,26 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
if (op == Token_ModMod) {
irValue *n = left;
irValue *m = right;
irValue *a = ir_emit(proc, ir_instr_binary_op(proc, Token_Mod, n, m, type));
irValue *b = ir_emit(proc, ir_instr_binary_op(proc, Token_Add, a, m, type));
return ir_emit(proc, ir_instr_binary_op(proc, Token_Mod, b, m, type));
irValue *a = ir_emit_arith(proc, Token_Mod, n, m, type);
irValue *b = ir_emit_arith(proc, Token_Add, a, m, type);
return ir_emit_arith(proc, Token_Mod, b, m, type);
}
if (is_type_i128_or_u128(type)) {
// IMPORTANT NOTE(bill): LLVM is goddamn buggy!
bool is_unsigned = is_type_unsigned(type);
char *name = NULL;
if (op == Token_Quo) {
name = is_unsigned ? "__udivti3" : "__divti3";
} else if (op == Token_Mod) {
name = is_unsigned ? "__umodti3" : "__modti3";
}
if (name != NULL) {
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 2);
args[0] = left;
args[1] = right;
return ir_emit_global_call(proc, name, args, 2);
}
}
return ir_emit(proc, ir_instr_binary_op(proc, op, left, right, type));
@@ -7529,6 +7546,8 @@ void ir_gen_tree(irGen *s) {
case Basic_u32:
case Basic_i64:
case Basic_u64:
case Basic_i128:
case Basic_u128:
case Basic_int:
case Basic_uint: {
tag = ir_emit_conv(proc, ti_ptr, t_type_info_integer_ptr);
+2 -5
View File
@@ -52,11 +52,6 @@ void ir_fprint_i128(irFileBuffer *f, i128 i) {
String str = i128_to_string(i, buf, gb_size_of(buf)-1);
ir_fprint_string(f, str);
}
void ir_fprint_u128(irFileBuffer *f, u128 i) {
char buf[200] = {0};
String str = u128_to_string(i, buf, gb_size_of(buf)-1);
ir_fprint_string(f, str);
}
void ir_file_write(irFileBuffer *f, void *data, isize len) {
ir_file_buffer_write(f, data, len);
@@ -195,6 +190,8 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
case Basic_u32: ir_fprintf(f, "i32"); return;
case Basic_i64: ir_fprintf(f, "i64"); return;
case Basic_u64: ir_fprintf(f, "i64"); return;
case Basic_i128: ir_fprintf(f, "i128"); return;
case Basic_u128: ir_fprintf(f, "i128"); return;
case Basic_f32: ir_fprintf(f, "float"); return;
case Basic_f64: ir_fprintf(f, "double"); return;
-1
View File
@@ -146,7 +146,6 @@ int main(int argc, char **argv) {
init_scratch_memory(gb_megabytes(10));
init_global_error_collector();
#if 1
init_build_context();
+15 -1
View File
@@ -11,6 +11,8 @@ typedef enum BasicKind {
Basic_u32,
Basic_i64,
Basic_u64,
Basic_i128,
Basic_u128,
Basic_f32,
Basic_f64,
@@ -224,6 +226,9 @@ gb_global Type basic_types[] = {
{Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, 4, STR_LIT("u32")}},
{Type_Basic, {Basic_i64, BasicFlag_Integer, 8, STR_LIT("i64")}},
{Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, 8, STR_LIT("u64")}},
{Type_Basic, {Basic_i128, BasicFlag_Integer, 16, STR_LIT("i128")}},
{Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, 16, STR_LIT("u128")}},
{Type_Basic, {Basic_f32, BasicFlag_Float, 4, STR_LIT("f32")}},
{Type_Basic, {Basic_f64, BasicFlag_Float, 8, STR_LIT("f64")}},
@@ -266,6 +271,8 @@ gb_global Type *t_i32 = &basic_types[Basic_i32];
gb_global Type *t_u32 = &basic_types[Basic_u32];
gb_global Type *t_i64 = &basic_types[Basic_i64];
gb_global Type *t_u64 = &basic_types[Basic_u64];
gb_global Type *t_i128 = &basic_types[Basic_i128];
gb_global Type *t_u128 = &basic_types[Basic_u128];
gb_global Type *t_f32 = &basic_types[Basic_f32];
gb_global Type *t_f64 = &basic_types[Basic_f64];
@@ -734,6 +741,12 @@ bool is_type_int_or_uint(Type *t) {
}
return false;
}
bool is_type_i128_or_u128(Type *t) {
if (t->kind == Type_Basic) {
return (t->Basic.kind == Basic_i128) || (t->Basic.kind == Basic_u128);
}
return false;
}
bool is_type_rawptr(Type *t) {
if (t->kind == Type_Basic) {
return t->Basic.kind == Basic_rawptr;
@@ -857,7 +870,8 @@ bool is_type_valid_for_keys(Type *t) {
return false;
}
if (is_type_integer(t)) {
return true;
// NOTE(bill): Not (u|i)128
return t->Basic.size <= 8;
}
if (is_type_float(t)) {
return true;