aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend.cpp
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2021-07-11 17:20:57 +0100
committerGitHub <noreply@github.com>2021-07-11 17:20:57 +0100
commit3600b2e209dd1826f7aa75de904854b142244dc0 (patch)
tree65ffe5965bfc1d12c598aa6ffc7a6a527919737f /src/llvm_backend.cpp
parentebcabb8a27ace67c3cd869a573df62b260000ee8 (diff)
parenteb36a0f3b138fd0058b75736f652e8fcf8422d8c (diff)
Merge pull request #1057 from odin-lang/new-big-int-library-integration
New Big Int Library Integration
Diffstat (limited to 'src/llvm_backend.cpp')
-rw-r--r--src/llvm_backend.cpp63
1 files changed, 34 insertions, 29 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index c351876d4..9198e6604 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -6362,7 +6362,38 @@ lbValue lb_find_value_from_entity(lbModule *m, Entity *e) {
}
+LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, BigInt const *a) {
+ if (big_int_is_zero(a)) {
+ return LLVMConstNull(lb_type(m, original_type));
+ }
+
+ 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(original_type)) {
+ endian = MP_LITTLE_ENDIAN;
+ } else if (is_type_endian_big(original_type)) {
+ endian = MP_BIG_ENDIAN;
+ }
+
+ 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,
+ a);
+ GB_ASSERT(err == MP_OKAY);
+ LLVMValueRef value = LLVMConstIntOfArbitraryPrecision(lb_type(m, original_type), cast(unsigned)((written+7)/8), cast(u64 *)rop);
+ if (big_int_is_neg(a)) {
+ value = LLVMConstNeg(value);
+ }
+
+ return value;
+}
lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_local) {
@@ -6558,37 +6589,11 @@ 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) {
- res.value = LLVMConstNull(t);
- } else {
- LLVMValueRef i = LLVMConstIntOfArbitraryPrecision(lb_type(m, t_uintptr), len, big_int_ptr(&value.value_integer));
- res.value = LLVMConstIntToPtr(i, t);
- }
+ LLVMValueRef i = lb_big_int_to_llvm(m, t_uintptr, &value.value_integer);
+ res.value = LLVMConstIntToPtr(i, t);
} else {
- unsigned len = cast(unsigned)value.value_integer.len;
- if (len == 0) {
- 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;
- }
- res.value = LLVMConstIntOfArbitraryPrecision(lb_type(m, original_type), len, words);
- if (value.value_integer.neg) {
- res.value = LLVMConstNeg(res.value);
- }
- }
+ res.value = lb_big_int_to_llvm(m, original_type, &value.value_integer);
}
return res;
case ExactValue_Float: