Change the compiler's big integer library to use libTomMath

This now replaces Bill's crappy big int implementation
This commit is contained in:
gingerBill
2021-07-11 16:08:16 +01:00
parent ebcabb8a27
commit 460e14e586
171 changed files with 10745 additions and 1155 deletions
+53 -19
View File
@@ -6558,36 +6558,70 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
case ExactValue_Integer:
if (is_type_pointer(type)) {
unsigned len = cast(unsigned)value.value_integer.len;
LLVMTypeRef t = lb_type(m, original_type);
if (len == 0) {
if (mp_iszero(&value.value_integer)) {
res.value = LLVMConstNull(t);
} else {
LLVMValueRef i = LLVMConstIntOfArbitraryPrecision(lb_type(m, t_uintptr), len, big_int_ptr(&value.value_integer));
unsigned len = cast(unsigned)value.value_integer.used;
u64 v = mp_get_u64(&value.value_integer);
LLVMValueRef i = LLVMConstInt(lb_type(m, t_uintptr), cast(unsigned long long)v, false);
res.value = LLVMConstIntToPtr(i, t);
}
} else {
unsigned len = cast(unsigned)value.value_integer.len;
if (len == 0) {
if (mp_iszero(&value.value_integer)) {
res.value = LLVMConstNull(lb_type(m, original_type));
} else {
u64 *words = big_int_ptr(&value.value_integer);
if (is_type_different_to_arch_endianness(type)) {
// NOTE(bill): Swap byte order for different endianness
i64 sz = type_size_of(type);
isize byte_len = gb_size_of(u64)*len;
u8 *old_bytes = cast(u8 *)words;
// TODO(bill): Use a different allocator here for a temporary allocation
u8 *new_bytes = cast(u8 *)gb_alloc_align(permanent_allocator(), byte_len, gb_align_of(u64));
for (i64 i = 0; i < sz; i++) {
new_bytes[i] = old_bytes[sz-1-i];
}
words = cast(u64 *)new_bytes;
mp_int *a = &value.value_integer;
u8 *rop = nullptr;
size_t max_count = 0;
size_t written = 0;
size_t size = 1;
size_t nails = 0;
mp_endian endian = MP_NATIVE_ENDIAN;
if (is_type_endian_little(type)) {
endian = MP_LITTLE_ENDIAN;
} else if (is_type_endian_big(type)) {
endian = MP_BIG_ENDIAN;
}
res.value = LLVMConstIntOfArbitraryPrecision(lb_type(m, original_type), len, words);
if (value.value_integer.neg) {
max_count = mp_pack_count(a, nails, size);
rop = cast(u8 *)gb_alloc_align(permanent_allocator(), max_count, gb_align_of(u64));
mp_err err = mp_pack(rop, max_count, &written,
MP_LSB_FIRST,
size, endian, nails,
&value.value_integer);
GB_ASSERT(err == MP_OKAY);
res.value = LLVMConstIntOfArbitraryPrecision(lb_type(m, original_type), cast(unsigned)((written+7)/8), cast(u64 *)rop);
if (value.value_integer.sign) {
res.value = LLVMConstNeg(res.value);
}
// size_t written = 0;
// size_t max_bytes = (value.value_integer.used*gb_size_of(mp_digit)+7)&~7;
// u8 *buf = cast(u8 *)gb_alloc_align(permanent_allocator(), max_bytes, gb_align_of(u64));
// mp_to_ubin(&value.value_integer, buf, max_bytes, &written);
// gb_printf_err("%tu %tu", written, max_bytes);
// for (size_t i = 0; i < written; i++) {
// gb_printf_err("%02x", buf[i]);
// }
// gb_printf_err("\n");
// gb_exit(1);
// if (is_type_different_to_arch_endianness(type)) {
// u8 *old_bytes = buf;
// u8 *new_bytes = cast(u8 *)gb_alloc_align(permanent_allocator(), max_bytes, gb_align_of(u64));
// for (size_t i = 0; i < written; i++) {
// new_bytes[i] = old_bytes[written-1-i];
// }
// buf = new_bytes;
// }
// res.value = LLVMConstIntOfArbitraryPrecision(lb_type(m, original_type), cast(unsigned)((written+7)/8), cast(u64 *)buf);
// if (value.value_integer.sign) {
// res.value = LLVMConstNeg(res.value);
// }
}
}
return res;