diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-06-01 14:23:46 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-06-01 14:23:46 +0100 |
| commit | 0d4945dc8788e8aa134fbdbd0941d9a6db0b67bc (patch) | |
| tree | 5344e3270f99746fdcee6237ebe768c1babfb822 /src | |
| parent | fec6df65b3306005077ee6124458eaaf3ea7ce2c (diff) | |
Implement u128/i128 features; Add bits.odin
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_decl.c | 20 | ||||
| -rw-r--r-- | src/check_expr.c | 6 | ||||
| -rw-r--r-- | src/gb/gb.h | 13 | ||||
| -rw-r--r-- | src/integer128.c | 72 | ||||
| -rw-r--r-- | src/ir.c | 25 | ||||
| -rw-r--r-- | src/ir_print.c | 7 | ||||
| -rw-r--r-- | src/main.c | 1 | ||||
| -rw-r--r-- | src/types.c | 16 |
8 files changed, 104 insertions, 56 deletions
diff --git a/src/check_decl.c b/src/check_decl.c index 725876665..6b15cdaca 100644 --- a/src/check_decl.c +++ b/src/check_decl.c @@ -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; } diff --git a/src/check_expr.c b/src/check_expr.c index a4a622341..2997cbbfb 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -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); diff --git a/src/gb/gb.h b/src/gb/gb.h index 9401eb923..0daec5e67 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -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); } diff --git a/src/integer128.c b/src/integer128.c index 70cf6bca0..ed05a1471 100644 --- a/src/integer128.c +++ b/src/integer128.c @@ -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; - - 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'; - } + isize i = gb_size_of(buf); - gb_reverse(buf, i, 1); + 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))]; - 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++] = '-'; - } - - 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; + buf[--i] = '-'; } - 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) { @@ -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); diff --git a/src/ir_print.c b/src/ir_print.c index 38c55bde9..5f45ce278 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -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; diff --git a/src/main.c b/src/main.c index 0e1af5907..d55278a75 100644 --- a/src/main.c +++ b/src/main.c @@ -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(); diff --git a/src/types.c b/src/types.c index bf699ecba..ff1b5abe8 100644 --- a/src/types.c +++ b/src/types.c @@ -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; |