aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-06-01 14:23:46 +0100
committerGinger Bill <bill@gingerbill.org>2017-06-01 14:23:46 +0100
commit0d4945dc8788e8aa134fbdbd0941d9a6db0b67bc (patch)
tree5344e3270f99746fdcee6237ebe768c1babfb822 /src
parentfec6df65b3306005077ee6124458eaaf3ea7ce2c (diff)
Implement u128/i128 features; Add bits.odin
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.c20
-rw-r--r--src/check_expr.c6
-rw-r--r--src/gb/gb.h13
-rw-r--r--src/integer128.c72
-rw-r--r--src/ir.c25
-rw-r--r--src/ir_print.c7
-rw-r--r--src/main.c1
-rw-r--r--src/types.c16
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) {
diff --git a/src/ir.c b/src/ir.c
index 6702096c4..e505865cd 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -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;