authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-06-26 14:41:47-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-07-08 17:59:10-04:00
logd1e68c3ca84844a96d4897c857861b40751965cc
tree8866451296719e1c1c0850bb31a213d081c22352
parent3e8af78895d313f0706389da2ad7e5c60df95964

better bigint/bigfloat implementation


25 files changed, 2095 insertions(+), 1143 deletions(-)

.gitignore+1
...@@ -7,3 +7,4 @@ build-llvm-debug/...@@ -7,3 +7,4 @@ build-llvm-debug/
7/.cproject7/.cproject
8/.project8/.project
9/.settings/9/.settings/
10build-llvm-debug/
CMakeLists.txt+2-1
...@@ -44,7 +44,8 @@ include_directories(...@@ -44,7 +44,8 @@ include_directories(
44set(ZIG_SOURCES44set(ZIG_SOURCES
45 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"45 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"
46 "${CMAKE_SOURCE_DIR}/src/ast_render.cpp"46 "${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
47 "${CMAKE_SOURCE_DIR}/src/bignum.cpp"47 "${CMAKE_SOURCE_DIR}/src/bigfloat.cpp"
48 "${CMAKE_SOURCE_DIR}/src/bigint.cpp"
48 "${CMAKE_SOURCE_DIR}/src/buffer.cpp"49 "${CMAKE_SOURCE_DIR}/src/buffer.cpp"
49 "${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp"50 "${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp"
50 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"51 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
doc/langref.md+1-1
...@@ -143,7 +143,7 @@ StructLiteralField = "." Symbol "=" Expression...@@ -143,7 +143,7 @@ StructLiteralField = "." Symbol "=" Expression
143143
144PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%"144PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%"
145145
146PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl146PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
147147
148ArrayType = "[" option(Expression) "]" option("const") TypeExpr148ArrayType = "[" option(Expression) "]" option("const") TypeExpr
149149
src/all_types.hpp+20-7
...@@ -13,7 +13,8 @@...@@ -13,7 +13,8 @@
13#include "zig_llvm.hpp"13#include "zig_llvm.hpp"
14#include "hash_map.hpp"14#include "hash_map.hpp"
15#include "errmsg.hpp"15#include "errmsg.hpp"
16#include "bignum.hpp"16#include "bigint.hpp"
17#include "bigfloat.hpp"
17#include "target.hpp"18#include "target.hpp"
1819
19struct AstNode;20struct AstNode;
...@@ -215,6 +216,11 @@ struct ConstGlobalRefs {...@@ -215,6 +216,11 @@ struct ConstGlobalRefs {
215 LLVMValueRef llvm_global;216 LLVMValueRef llvm_global;
216};217};
217218
219enum ConstNumLitKind {
220 ConstNumLitKindInt,
221 ConstNumLitKindFloat,
222};
223
218struct ConstExprValue {224struct ConstExprValue {
219 TypeTableEntry *type;225 TypeTableEntry *type;
220 ConstValSpecial special;226 ConstValSpecial special;
...@@ -222,7 +228,8 @@ struct ConstExprValue {...@@ -222,7 +228,8 @@ struct ConstExprValue {
222228
223 union {229 union {
224 // populated if special == ConstValSpecialStatic230 // populated if special == ConstValSpecialStatic
225 BigNum x_bignum;231 BigInt x_bigint;
232 BigFloat x_bigfloat;
226 bool x_bool;233 bool x_bool;
227 ConstFn x_fn;234 ConstFn x_fn;
228 ConstBoundFnValue x_bound_fn;235 ConstBoundFnValue x_bound_fn;
...@@ -347,7 +354,8 @@ enum NodeType {...@@ -347,7 +354,8 @@ enum NodeType {
347 NodeTypeTestDecl,354 NodeTypeTestDecl,
348 NodeTypeBinOpExpr,355 NodeTypeBinOpExpr,
349 NodeTypeUnwrapErrorExpr,356 NodeTypeUnwrapErrorExpr,
350 NodeTypeNumberLiteral,357 NodeTypeFloatLiteral,
358 NodeTypeIntLiteral,
351 NodeTypeStringLiteral,359 NodeTypeStringLiteral,
352 NodeTypeCharLiteral,360 NodeTypeCharLiteral,
353 NodeTypeSymbol,361 NodeTypeSymbol,
...@@ -748,14 +756,18 @@ struct AstNodeCharLiteral {...@@ -748,14 +756,18 @@ struct AstNodeCharLiteral {
748 uint8_t value;756 uint8_t value;
749};757};
750758
751struct AstNodeNumberLiteral {759struct AstNodeFloatLiteral {
752 BigNum *bignum;760 BigFloat *bigfloat;
753761
754 // overflow is true if when parsing the number, we discovered it would not762 // overflow is true if when parsing the number, we discovered it would not
755 // fit without losing data in a uint64_t or double763 // fit without losing data in a double
756 bool overflow;764 bool overflow;
757};765};
758766
767struct AstNodeIntLiteral {
768 BigInt *bigint;
769};
770
759struct AstNodeStructValueField {771struct AstNodeStructValueField {
760 Buf *name;772 Buf *name;
761 AstNode *expr;773 AstNode *expr;
...@@ -854,7 +866,8 @@ struct AstNode {...@@ -854,7 +866,8 @@ struct AstNode {
854 AstNodeStructField struct_field;866 AstNodeStructField struct_field;
855 AstNodeStringLiteral string_literal;867 AstNodeStringLiteral string_literal;
856 AstNodeCharLiteral char_literal;868 AstNodeCharLiteral char_literal;
857 AstNodeNumberLiteral number_literal;869 AstNodeFloatLiteral float_literal;
870 AstNodeIntLiteral int_literal;
858 AstNodeContainerInitExpr container_init_expr;871 AstNodeContainerInitExpr container_init_expr;
859 AstNodeStructValueField struct_val_field;872 AstNodeStructValueField struct_val_field;
860 AstNodeNullLiteral null_literal;873 AstNodeNullLiteral null_literal;
src/analyze.cpp+58-76
...@@ -2194,7 +2194,8 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -2194,7 +2194,8 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
2194 case NodeTypeFnCallExpr:2194 case NodeTypeFnCallExpr:
2195 case NodeTypeArrayAccessExpr:2195 case NodeTypeArrayAccessExpr:
2196 case NodeTypeSliceExpr:2196 case NodeTypeSliceExpr:
2197 case NodeTypeNumberLiteral:2197 case NodeTypeFloatLiteral:
2198 case NodeTypeIntLiteral:
2198 case NodeTypeStringLiteral:2199 case NodeTypeStringLiteral:
2199 case NodeTypeCharLiteral:2200 case NodeTypeCharLiteral:
2200 case NodeTypeBoolLiteral:2201 case NodeTypeBoolLiteral:
...@@ -3247,10 +3248,17 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {...@@ -3247,10 +3248,17 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
3247 case TypeTableEntryIdInt:3248 case TypeTableEntryIdInt:
3248 case TypeTableEntryIdNumLitInt:3249 case TypeTableEntryIdNumLitInt:
3249 case TypeTableEntryIdEnumTag:3250 case TypeTableEntryIdEnumTag:
3250 return ((uint32_t)(bignum_to_twos_complement(&const_val->data.x_bignum) % UINT32_MAX)) * (uint32_t)1331471175;3251 {
3252 uint32_t result = 1331471175;
3253 for (size_t i = 0; i < const_val->data.x_bigint.digit_count; i += 1) {
3254 uint64_t digit = bigint_ptr(&const_val->data.x_bigint)[i];
3255 result ^= ((uint32_t)(digit >> 32)) ^ (uint32_t)(result);
3256 }
3257 return result;
3258 }
3251 case TypeTableEntryIdFloat:3259 case TypeTableEntryIdFloat:
3252 case TypeTableEntryIdNumLitFloat:3260 case TypeTableEntryIdNumLitFloat:
3253 return (uint32_t)(const_val->data.x_bignum.data.x_float * (uint32_t)UINT32_MAX);3261 return (uint32_t)(const_val->data.x_bigfloat.value * (uint32_t)UINT32_MAX);
3254 case TypeTableEntryIdArgTuple:3262 case TypeTableEntryIdArgTuple:
3255 return (uint32_t)const_val->data.x_arg_tuple.start_index * (uint32_t)281907309 +3263 return (uint32_t)const_val->data.x_arg_tuple.start_index * (uint32_t)281907309 +
3256 (uint32_t)const_val->data.x_arg_tuple.end_index * (uint32_t)2290442768;3264 (uint32_t)const_val->data.x_arg_tuple.end_index * (uint32_t)2290442768;
...@@ -3473,7 +3481,7 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -3473,7 +3481,7 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
3473 ConstExprValue *this_char = &const_val->data.x_array.s_none.elements[i];3481 ConstExprValue *this_char = &const_val->data.x_array.s_none.elements[i];
3474 this_char->special = ConstValSpecialStatic;3482 this_char->special = ConstValSpecialStatic;
3475 this_char->type = g->builtin_types.entry_u8;3483 this_char->type = g->builtin_types.entry_u8;
3476 bignum_init_unsigned(&this_char->data.x_bignum, (uint8_t)buf_ptr(str)[i]);3484 bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(str)[i]);
3477 }3485 }
3478}3486}
34793487
...@@ -3494,12 +3502,12 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -3494,12 +3502,12 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
3494 ConstExprValue *this_char = &array_val->data.x_array.s_none.elements[i];3502 ConstExprValue *this_char = &array_val->data.x_array.s_none.elements[i];
3495 this_char->special = ConstValSpecialStatic;3503 this_char->special = ConstValSpecialStatic;
3496 this_char->type = g->builtin_types.entry_u8;3504 this_char->type = g->builtin_types.entry_u8;
3497 bignum_init_unsigned(&this_char->data.x_bignum, (uint8_t)buf_ptr(str)[i]);3505 bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(str)[i]);
3498 }3506 }
3499 ConstExprValue *null_char = &array_val->data.x_array.s_none.elements[len_with_null - 1];3507 ConstExprValue *null_char = &array_val->data.x_array.s_none.elements[len_with_null - 1];
3500 null_char->special = ConstValSpecialStatic;3508 null_char->special = ConstValSpecialStatic;
3501 null_char->type = g->builtin_types.entry_u8;3509 null_char->type = g->builtin_types.entry_u8;
3502 bignum_init_unsigned(&null_char->data.x_bignum, 0);3510 bigint_init_unsigned(&null_char->data.x_bigint, 0);
35033511
3504 // then make the pointer point to it3512 // then make the pointer point to it
3505 const_val->special = ConstValSpecialStatic;3513 const_val->special = ConstValSpecialStatic;
...@@ -3518,8 +3526,8 @@ ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {...@@ -3518,8 +3526,8 @@ ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {
3518void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) {3526void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) {
3519 const_val->special = ConstValSpecialStatic;3527 const_val->special = ConstValSpecialStatic;
3520 const_val->type = type;3528 const_val->type = type;
3521 bignum_init_unsigned(&const_val->data.x_bignum, x);3529 bigint_init_unsigned(&const_val->data.x_bigint, x);
3522 const_val->data.x_bignum.is_negative = negative;3530 const_val->data.x_bigint.is_negative = negative;
3523}3531}
35243532
3525ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative) {3533ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative) {
...@@ -3539,7 +3547,7 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x) {...@@ -3539,7 +3547,7 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x) {
3539void init_const_signed(ConstExprValue *const_val, TypeTableEntry *type, int64_t x) {3547void init_const_signed(ConstExprValue *const_val, TypeTableEntry *type, int64_t x) {
3540 const_val->special = ConstValSpecialStatic;3548 const_val->special = ConstValSpecialStatic;
3541 const_val->type = type;3549 const_val->type = type;
3542 bignum_init_signed(&const_val->data.x_bignum, x);3550 bigint_init_signed(&const_val->data.x_bigint, x);
3543}3551}
35443552
3545ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x) {3553ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x) {
...@@ -3551,7 +3559,7 @@ ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x) {...@@ -3551,7 +3559,7 @@ ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x) {
3551void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value) {3559void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value) {
3552 const_val->special = ConstValSpecialStatic;3560 const_val->special = ConstValSpecialStatic;
3553 const_val->type = type;3561 const_val->type = type;
3554 bignum_init_float(&const_val->data.x_bignum, value);3562 bigfloat_init_float(&const_val->data.x_bigfloat, value);
3555}3563}
35563564
3557ConstExprValue *create_const_float(TypeTableEntry *type, double value) {3565ConstExprValue *create_const_float(TypeTableEntry *type, double value) {
...@@ -3788,12 +3796,13 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {...@@ -3788,12 +3796,13 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
3788 return a->data.x_fn.fn_entry == b->data.x_fn.fn_entry;3796 return a->data.x_fn.fn_entry == b->data.x_fn.fn_entry;
3789 case TypeTableEntryIdBool:3797 case TypeTableEntryIdBool:
3790 return a->data.x_bool == b->data.x_bool;3798 return a->data.x_bool == b->data.x_bool;
3791 case TypeTableEntryIdInt:
3792 case TypeTableEntryIdFloat:3799 case TypeTableEntryIdFloat:
3793 case TypeTableEntryIdNumLitFloat:3800 case TypeTableEntryIdNumLitFloat:
3801 return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ;
3802 case TypeTableEntryIdInt:
3794 case TypeTableEntryIdNumLitInt:3803 case TypeTableEntryIdNumLitInt:
3795 case TypeTableEntryIdEnumTag:3804 case TypeTableEntryIdEnumTag:
3796 return bignum_cmp_eq(&a->data.x_bignum, &b->data.x_bignum);3805 return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ;
3797 case TypeTableEntryIdPointer:3806 case TypeTableEntryIdPointer:
3798 if (a->data.x_ptr.special != b->data.x_ptr.special)3807 if (a->data.x_ptr.special != b->data.x_ptr.special)
3799 return false;3808 return false;
...@@ -3876,58 +3885,47 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {...@@ -3876,58 +3885,47 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
3876 zig_unreachable();3885 zig_unreachable();
3877}3886}
38783887
3879uint64_t max_unsigned_val(TypeTableEntry *type_entry) {3888void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max) {
3880 assert(type_entry->id == TypeTableEntryIdInt);3889 assert(int_type->id == TypeTableEntryIdInt);
3881 if (type_entry->data.integral.bit_count == 64) {3890 if (int_type->data.integral.bit_count == 0) {
3882 return UINT64_MAX;3891 bigint_init_unsigned(bigint, 0);
3883 } else {3892 return;
3884 return (((uint64_t)1) << type_entry->data.integral.bit_count) - 1;
3885 }3893 }
3886}3894 if (is_max) {
3895 // is_signed=true (1 << (bit_count - 1)) - 1
3896 // is_signed=false (1 << (bit_count - 0)) - 1
3897 BigInt one = {0};
3898 bigint_init_unsigned(&one, 1);
38873899
3888static int64_t max_signed_val(TypeTableEntry *type_entry) {3900 size_t shift_amt = int_type->data.integral.bit_count - (int_type->data.integral.is_signed ? 1 : 0);
3889 assert(type_entry->id == TypeTableEntryIdInt);3901 BigInt bit_count_bi = {0};
3902 bigint_init_unsigned(&bit_count_bi, shift_amt);
38903903
3891 if (type_entry->data.integral.bit_count == 64) {3904 BigInt shifted_bi = {0};
3892 return INT64_MAX;3905 bigint_shl(&shifted_bi, &one, &bit_count_bi);
3893 } else {
3894 return (((uint64_t)1) << (type_entry->data.integral.bit_count - 1)) - 1;
3895 }
3896}
38973906
3898int64_t min_signed_val(TypeTableEntry *type_entry) {3907 bigint_sub(bigint, &shifted_bi, &one);
3899 assert(type_entry->id == TypeTableEntryIdInt);3908 } else if (int_type->data.integral.is_signed) {
3900 if (type_entry->data.integral.bit_count == 64) {3909 // - (1 << (bit_count - 1))
3901 return INT64_MIN;3910 BigInt one = {0};
3902 } else {3911 bigint_init_unsigned(&one, 1);
3903 return -((int64_t)(((uint64_t)1) << (type_entry->data.integral.bit_count - 1)));
3904 }
3905}
39063912
3907void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigNum *bignum, bool is_max) {3913 BigInt bit_count_bi = {0};
3908 assert(int_type->id == TypeTableEntryIdInt);3914 bigint_init_unsigned(&bit_count_bi, int_type->data.integral.bit_count - 1);
3909 if (is_max) {3915
3910 if (int_type->data.integral.is_signed) {3916 BigInt shifted_bi = {0};
3911 int64_t val = max_signed_val(int_type);3917 bigint_shl(&shifted_bi, &one, &bit_count_bi);
3912 bignum_init_signed(bignum, val);3918
3913 } else {3919 bigint_negate(bigint, &shifted_bi);
3914 uint64_t val = max_unsigned_val(int_type);
3915 bignum_init_unsigned(bignum, val);
3916 }
3917 } else {3920 } else {
3918 if (int_type->data.integral.is_signed) {3921 bigint_init_unsigned(bigint, 0);
3919 int64_t val = min_signed_val(int_type);
3920 bignum_init_signed(bignum, val);
3921 } else {
3922 bignum_init_unsigned(bignum, 0);
3923 }
3924 }3922 }
3925}3923}
39263924
3927void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) {3925void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) {
3928 if (type_entry->id == TypeTableEntryIdInt) {3926 if (type_entry->id == TypeTableEntryIdInt) {
3929 const_val->special = ConstValSpecialStatic;3927 const_val->special = ConstValSpecialStatic;
3930 eval_min_max_value_int(g, type_entry, &const_val->data.x_bignum, is_max);3928 eval_min_max_value_int(g, type_entry, &const_val->data.x_bigint, is_max);
3931 } else if (type_entry->id == TypeTableEntryIdFloat) {3929 } else if (type_entry->id == TypeTableEntryIdFloat) {
3932 zig_panic("TODO analyze_min_max_value float");3930 zig_panic("TODO analyze_min_max_value float");
3933 } else if (type_entry->id == TypeTableEntryIdBool) {3931 } else if (type_entry->id == TypeTableEntryIdBool) {
...@@ -3967,32 +3965,15 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -3967,32 +3965,15 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
3967 buf_appendf(buf, "{}");3965 buf_appendf(buf, "{}");
3968 return;3966 return;
3969 case TypeTableEntryIdNumLitFloat:3967 case TypeTableEntryIdNumLitFloat:
3970 buf_appendf(buf, "%f", const_val->data.x_bignum.data.x_float);3968 case TypeTableEntryIdFloat:
3969 bigfloat_write_buf(buf, &const_val->data.x_bigfloat);
3971 return;3970 return;
3972 case TypeTableEntryIdNumLitInt:3971 case TypeTableEntryIdNumLitInt:
3973 {
3974 BigNum *bignum = &const_val->data.x_bignum;
3975 const char *negative_str = bignum->is_negative ? "-" : "";
3976 buf_appendf(buf, "%s%" ZIG_PRI_llu, negative_str, bignum->data.x_uint);
3977 return;
3978 }
3979 case TypeTableEntryIdMetaType:
3980 buf_appendf(buf, "%s", buf_ptr(&const_val->data.x_type->name));
3981 return;
3982 case TypeTableEntryIdInt:3972 case TypeTableEntryIdInt:
3983 {3973 bigint_write_buf(buf, &const_val->data.x_bigint, 10);
3984 BigNum *bignum = &const_val->data.x_bignum;
3985 assert(bignum->kind == BigNumKindInt);
3986 const char *negative_str = bignum->is_negative ? "-" : "";
3987 buf_appendf(buf, "%s%" ZIG_PRI_llu, negative_str, bignum->data.x_uint);
3988 }
3989 return;3974 return;
3990 case TypeTableEntryIdFloat:3975 case TypeTableEntryIdMetaType:
3991 {3976 buf_appendf(buf, "%s", buf_ptr(&const_val->data.x_type->name));
3992 BigNum *bignum = &const_val->data.x_bignum;
3993 assert(bignum->kind == BigNumKindFloat);
3994 buf_appendf(buf, "%f", bignum->data.x_float);
3995 }
3996 return;3977 return;
3997 case TypeTableEntryIdUnreachable:3978 case TypeTableEntryIdUnreachable:
3998 buf_appendf(buf, "@unreachable()");3979 buf_appendf(buf, "@unreachable()");
...@@ -4060,7 +4041,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -4060,7 +4041,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
4060 buf_append_char(buf, '"');4041 buf_append_char(buf, '"');
4061 for (uint64_t i = 0; i < len; i += 1) {4042 for (uint64_t i = 0; i < len; i += 1) {
4062 ConstExprValue *child_value = &const_val->data.x_array.s_none.elements[i];4043 ConstExprValue *child_value = &const_val->data.x_array.s_none.elements[i];
4063 uint64_t big_c = child_value->data.x_bignum.data.x_uint;4044 uint64_t big_c = bigint_as_unsigned(&child_value->data.x_bigint);
4064 assert(big_c <= UINT8_MAX);4045 assert(big_c <= UINT8_MAX);
4065 uint8_t c = (uint8_t)big_c;4046 uint8_t c = (uint8_t)big_c;
4066 if (c == '"') {4047 if (c == '"') {
...@@ -4146,7 +4127,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -4146,7 +4127,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
4146 case TypeTableEntryIdEnumTag:4127 case TypeTableEntryIdEnumTag:
4147 {4128 {
4148 TypeTableEntry *enum_type = type_entry->data.enum_tag.enum_type;4129 TypeTableEntry *enum_type = type_entry->data.enum_tag.enum_type;
4149 TypeEnumField *field = &enum_type->data.enumeration.fields[const_val->data.x_bignum.data.x_uint];4130 size_t field_index = bigint_as_unsigned(&const_val->data.x_bigint);
4131 TypeEnumField *field = &enum_type->data.enumeration.fields[field_index];
4150 buf_appendf(buf, "%s.%s", buf_ptr(&enum_type->name), buf_ptr(field->name));4132 buf_appendf(buf, "%s.%s", buf_ptr(&enum_type->name), buf_ptr(field->name));
4151 return;4133 return;
4152 }4134 }
src/analyze.hpp+1-3
...@@ -84,9 +84,7 @@ void complete_enum(CodeGen *g, TypeTableEntry *enum_type);...@@ -84,9 +84,7 @@ void complete_enum(CodeGen *g, TypeTableEntry *enum_type);
84bool ir_get_var_is_comptime(VariableTableEntry *var);84bool ir_get_var_is_comptime(VariableTableEntry *var);
85bool const_values_equal(ConstExprValue *a, ConstExprValue *b);85bool const_values_equal(ConstExprValue *a, ConstExprValue *b);
86void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max);86void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max);
87void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigNum *bignum, bool is_max);87void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max);
88int64_t min_signed_val(TypeTableEntry *type_entry);
89uint64_t max_unsigned_val(TypeTableEntry *type_entry);
9088
91void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);89void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);
92void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars);90void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars);
src/ast_render.cpp+18-13
...@@ -182,8 +182,10 @@ static const char *node_type_str(NodeType node_type) {...@@ -182,8 +182,10 @@ static const char *node_type_str(NodeType node_type) {
182 return "ErrorValueDecl";182 return "ErrorValueDecl";
183 case NodeTypeTestDecl:183 case NodeTypeTestDecl:
184 return "TestDecl";184 return "TestDecl";
185 case NodeTypeNumberLiteral:185 case NodeTypeIntLiteral:
186 return "NumberLiteral";186 return "IntLiteral";
187 case NodeTypeFloatLiteral:
188 return "FloatLiteral";
187 case NodeTypeStringLiteral:189 case NodeTypeStringLiteral:
188 return "StringLiteral";190 return "StringLiteral";
189 case NodeTypeCharLiteral:191 case NodeTypeCharLiteral:
...@@ -536,17 +538,20 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -536,17 +538,20 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
536 render_node_ungrouped(ar, node->data.bin_op_expr.op2);538 render_node_ungrouped(ar, node->data.bin_op_expr.op2);
537 if (!grouped) fprintf(ar->f, ")");539 if (!grouped) fprintf(ar->f, ")");
538 break;540 break;
539 case NodeTypeNumberLiteral:541 case NodeTypeFloatLiteral:
540 switch (node->data.number_literal.bignum->kind) {542 {
541 case BigNumKindInt:543 Buf rendered_buf = BUF_INIT;
542 {544 buf_resize(&rendered_buf, 0);
543 const char *negative_str = node->data.number_literal.bignum->is_negative ? "-" : "";545 bigfloat_write_buf(&rendered_buf, node->data.float_literal.bigfloat);
544 fprintf(ar->f, "%s%" ZIG_PRI_llu, negative_str, node->data.number_literal.bignum->data.x_uint);546 fprintf(ar->f, "%s", buf_ptr(&rendered_buf));
545 }547 }
546 break;548 break;
547 case BigNumKindFloat:549 case NodeTypeIntLiteral:
548 fprintf(ar->f, "%f", node->data.number_literal.bignum->data.x_float);550 {
549 break;551 Buf rendered_buf = BUF_INIT;
552 buf_resize(&rendered_buf, 0);
553 bigint_write_buf(&rendered_buf, node->data.int_literal.bigint, 10);
554 fprintf(ar->f, "%s", buf_ptr(&rendered_buf));
550 }555 }
551 break;556 break;
552 case NodeTypeStringLiteral:557 case NodeTypeStringLiteral:
src/bigfloat.cpp created+152
...@@ -0,0 +1,152 @@
1/*
2 * Copyright (c) 2017 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "bigfloat.hpp"
9#include "bigint.hpp"
10#include "buffer.hpp"
11#include <math.h>
12#include <errno.h>
13
14void bigfloat_init_float(BigFloat *dest, long double x) {
15 dest->value = x;
16}
17
18void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x) {
19 dest->value = x->value;
20}
21
22void bigfloat_init_bigint(BigFloat *dest, const BigInt *op) {
23 dest->value = 0.0;
24 if (op->digit_count == 0)
25 return;
26
27 long double base = (long double)UINT64_MAX;
28 const uint64_t *digits = bigint_ptr(op);
29
30 for (size_t i = op->digit_count - 1;;) {
31 uint64_t digit = digits[i];
32 dest->value *= base;
33 dest->value += (long double)digit;
34
35 if (i == 0) {
36 if (op->is_negative) {
37 dest->value = -dest->value;
38 }
39 return;
40 }
41 i -= 1;
42 }
43}
44
45int bigfloat_init_buf_base10(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len) {
46 char *str_begin = (char *)buf_ptr;
47 char *str_end;
48 errno = 0;
49 dest->value = strtold(str_begin, &str_end);
50 if (errno) {
51 return ErrorOverflow;
52 }
53 assert(str_end <= ((char*)buf_ptr) + buf_len);
54 return 0;
55}
56
57void bigfloat_add(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
58 dest->value = op1->value + op2->value;
59}
60
61void bigfloat_negate(BigFloat *dest, const BigFloat *op) {
62 dest->value = -op->value;
63}
64
65void bigfloat_sub(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
66 dest->value = op1->value - op2->value;
67}
68
69void bigfloat_mul(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
70 dest->value = op1->value * op2->value;
71}
72
73void bigfloat_div(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
74 dest->value = op1->value / op2->value;
75}
76
77void bigfloat_div_trunc(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
78 dest->value = op1->value / op2->value;
79 if (dest->value >= 0.0) {
80 dest->value = floorl(dest->value);
81 } else {
82 dest->value = ceill(dest->value);
83 }
84}
85
86void bigfloat_div_floor(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
87 dest->value = floorl(op1->value / op2->value);
88}
89
90void bigfloat_rem(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
91 dest->value = fmodl(op1->value, op2->value);
92}
93
94void bigfloat_mod(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
95 dest->value = fmodl(fmodl(op1->value, op2->value) + op2->value, op2->value);
96}
97
98void bigfloat_write_buf(Buf *buf, const BigFloat *op) {
99 buf_appendf(buf, "%Lf", op->value);
100}
101
102Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2) {
103 if (op1->value > op2->value) {
104 return CmpGT;
105 } else if (op1->value < op2->value) {
106 return CmpLT;
107 } else {
108 return CmpEQ;
109 }
110}
111
112// TODO this is wrong when compiler running on big endian systems. caught by tests
113void bigfloat_write_ieee597(const BigFloat *op, uint8_t *buf, size_t bit_count, bool is_big_endian) {
114 if (bit_count == 32) {
115 float f32 = op->value;
116 memcpy(buf, &f32, 4);
117 } else if (bit_count == 64) {
118 double f64 = op->value;
119 memcpy(buf, &f64, 8);
120 } else {
121 zig_unreachable();
122 }
123}
124
125// TODO this is wrong when compiler running on big endian systems. caught by tests
126void bigfloat_read_ieee597(BigFloat *dest, const uint8_t *buf, size_t bit_count, bool is_big_endian) {
127 if (bit_count == 32) {
128 float f32;
129 memcpy(&f32, buf, 4);
130 dest->value = f32;
131 } else if (bit_count == 64) {
132 double f64;
133 memcpy(&f64, buf, 8);
134 dest->value = f64;
135 } else {
136 zig_unreachable();
137 }
138}
139
140double bigfloat_to_double(const BigFloat *bigfloat) {
141 return bigfloat->value;
142}
143
144Cmp bigfloat_cmp_zero(const BigFloat *bigfloat) {
145 if (bigfloat->value < 0.0) {
146 return CmpLT;
147 } else if (bigfloat->value > 0.0) {
148 return CmpGT;
149 } else {
150 return CmpEQ;
151 }
152}
src/bigfloat.hpp created+47
...@@ -0,0 +1,47 @@
1/*
2 * Copyright (c) 2017 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_BIGFLOAT_HPP
9#define ZIG_BIGFLOAT_HPP
10
11#include "bigint.hpp"
12#include "error.hpp"
13#include <stdint.h>
14#include <stddef.h>
15
16struct BigFloat {
17 long double value;
18};
19
20struct Buf;
21
22void bigfloat_init_float(BigFloat *dest, long double x);
23void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x);
24void bigfloat_init_bigint(BigFloat *dest, const BigInt *op);
25int bigfloat_init_buf_base10(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len);
26
27double bigfloat_to_double(const BigFloat *bigfloat);
28
29void bigfloat_add(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
30void bigfloat_negate(BigFloat *dest, const BigFloat *op);
31void bigfloat_sub(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
32void bigfloat_mul(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
33void bigfloat_div(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
34void bigfloat_div_trunc(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
35void bigfloat_div_floor(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
36void bigfloat_rem(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
37void bigfloat_mod(BigFloat *dest, const BigFloat *op1, const BigFloat *op2);
38void bigfloat_write_buf(Buf *buf, const BigFloat *op);
39Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2);
40void bigfloat_write_ieee597(const BigFloat *op, uint8_t *buf, size_t bit_count, bool is_big_endian);
41void bigfloat_read_ieee597(BigFloat *dest, const uint8_t *buf, size_t bit_count, bool is_big_endian);
42
43
44// convenience functions
45Cmp bigfloat_cmp_zero(const BigFloat *bigfloat);
46
47#endif
src/bigint.cpp created+1088
...@@ -0,0 +1,1088 @@
1/*
2 * Copyright (c) 2017 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "bigfloat.hpp"
9#include "bigint.hpp"
10#include "buffer.hpp"
11#include "list.hpp"
12#include "os.hpp"
13
14static void bigint_normalize(BigInt *dest) {
15 const uint64_t *digits = bigint_ptr(dest);
16
17 size_t last_nonzero_digit = SIZE_MAX;
18 for (size_t i = 0; i < dest->digit_count; i += 1) {
19 uint64_t digit = digits[i];
20 if (digit != 0) {
21 last_nonzero_digit = i;
22 }
23 }
24 if (last_nonzero_digit == SIZE_MAX) {
25 dest->is_negative = false;
26 dest->digit_count = 0;
27 } else {
28 dest->digit_count = last_nonzero_digit + 1;
29 if (last_nonzero_digit == 0) {
30 dest->data.digit = digits[0];
31 }
32 }
33}
34
35static uint8_t digit_to_char(uint8_t digit, bool uppercase) {
36 if (digit <= 9) {
37 return digit + '0';
38 } else if (digit <= 35) {
39 return digit + (uppercase ? 'A' : 'a');
40 } else {
41 zig_unreachable();
42 }
43}
44
45size_t bigint_bits_needed(const BigInt *op) {
46 size_t full_bits = op->digit_count * 64;
47 size_t leading_zero_count = bigint_clz(op, full_bits);
48 size_t bits_needed = full_bits - leading_zero_count;
49 return bits_needed + op->is_negative;
50}
51
52static void to_twos_complement(BigInt *dest, const BigInt *op, size_t bit_count) {
53 if (bit_count == 0 || op->digit_count == 0) {
54 bigint_init_unsigned(dest, 0);
55 return;
56 }
57 if (op->is_negative) {
58 BigInt negated = {0};
59 bigint_negate(&negated, op);
60
61 BigInt inverted = {0};
62 bigint_not(&inverted, &negated, bit_count, false);
63
64 BigInt one = {0};
65 bigint_init_unsigned(&one, 1);
66
67 bigint_add(dest, &inverted, &one);
68 return;
69 }
70
71 dest->is_negative = false;
72 const uint64_t *op_digits = bigint_ptr(op);
73 if (op->digit_count == 1) {
74 dest->data.digit = op_digits[0];
75 if (bit_count < 64) {
76 dest->data.digit &= (1ULL << bit_count) - 1;
77 }
78 dest->digit_count = 1;
79 bigint_normalize(dest);
80 return;
81 }
82 size_t digits_to_copy = bit_count / 64;
83 size_t leftover_bits = bit_count % 64;
84 dest->digit_count = digits_to_copy + ((leftover_bits == 0) ? 0 : 1);
85 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
86 for (size_t i = 0; i < digits_to_copy; i += 1) {
87 uint64_t digit = (i < op->digit_count) ? op_digits[i] : 0;
88 dest->data.digits[i] = digit;
89 }
90 if (leftover_bits != 0) {
91 uint64_t digit = (digits_to_copy < op->digit_count) ? op_digits[digits_to_copy] : 0;
92 dest->data.digits[digits_to_copy] = digit & ((1ULL << leftover_bits) - 1);
93 }
94 bigint_normalize(dest);
95}
96
97static bool bit_at_index(const BigInt *bi, size_t index) {
98 size_t digit_index = bi->digit_count - (index / 64) - 1;
99 size_t digit_bit_index = index % 64;
100 const uint64_t *digits = bigint_ptr(bi);
101 uint64_t digit = digits[digit_index];
102 return ((digit >> digit_bit_index) & 0x1) == 0x1;
103}
104
105static void from_twos_complement(BigInt *dest, const BigInt *src, size_t bit_count, bool is_signed) {
106 assert(!src->is_negative);
107
108 if (bit_count == 0 || src->digit_count == 0) {
109 bigint_init_unsigned(dest, 0);
110 return;
111 }
112
113 if (is_signed && bit_at_index(src, bit_count - 1)) {
114 BigInt negative_one = {0};
115 bigint_init_signed(&negative_one, -1);
116
117 BigInt minus_one = {0};
118 bigint_add(&minus_one, src, &negative_one);
119
120 BigInt inverted = {0};
121 bigint_not(&inverted, &minus_one, bit_count, false);
122
123 bigint_negate(dest, &inverted);
124 return;
125
126 }
127
128 bigint_init_bigint(dest, src);
129}
130
131void bigint_init_unsigned(BigInt *dest, uint64_t x) {
132 if (x == 0) {
133 dest->digit_count = 0;
134 dest->is_negative = false;
135 return;
136 }
137 dest->digit_count = 1;
138 dest->data.digit = x;
139 dest->is_negative = false;
140}
141
142void bigint_init_signed(BigInt *dest, int64_t x) {
143 if (x >= 0) {
144 return bigint_init_unsigned(dest, x);
145 }
146 dest->is_negative = true;
147 dest->digit_count = 1;
148 dest->data.digit = ((uint64_t)(-(x + 1))) + 1;
149}
150
151void bigint_init_bigint(BigInt *dest, const BigInt *src) {
152 if (src->digit_count == 0) {
153 return bigint_init_unsigned(dest, 0);
154 } else if (src->digit_count == 1) {
155 dest->digit_count = 1;
156 dest->data.digit = src->data.digit;
157 dest->is_negative = src->is_negative;
158 return;
159 }
160 dest->is_negative = src->is_negative;
161 dest->digit_count = src->digit_count;
162 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
163 memcpy(dest->data.digits, src->data.digits, sizeof(uint64_t) * dest->digit_count);
164}
165
166void bigint_init_bigfloat(BigInt *dest, const BigFloat *op) {
167 if (op->value >= 0) {
168 bigint_init_unsigned(dest, op->value);
169 } else {
170 bigint_init_unsigned(dest, -op->value);
171 dest->is_negative = true;
172 }
173}
174
175bool bigint_fits_in_bits(const BigInt *bn, size_t bit_count, bool is_signed) {
176 assert(bn->digit_count != 1 || bn->data.digit != 0);
177 if (bit_count == 0) {
178 return bigint_cmp_zero(bn) == CmpEQ;
179 }
180 if (bn->digit_count == 0) {
181 return true;
182 }
183
184 if (!is_signed) {
185 size_t full_bits = bn->digit_count * 64;
186 size_t leading_zero_count = bigint_clz(bn, full_bits);
187 return bit_count >= full_bits - leading_zero_count;
188 }
189
190 BigInt one = {0};
191 bigint_init_unsigned(&one, 1);
192
193 BigInt shl_amt = {0};
194 bigint_init_unsigned(&shl_amt, bit_count - 1);
195
196 BigInt max_value_plus_one = {0};
197 bigint_shl(&max_value_plus_one, &one, &shl_amt);
198
199 BigInt max_value = {0};
200 bigint_sub(&max_value, &max_value_plus_one, &one);
201
202 BigInt min_value = {0};
203 bigint_negate(&min_value, &max_value_plus_one);
204
205 Cmp min_cmp = bigint_cmp(bn, &min_value);
206 Cmp max_cmp = bigint_cmp(bn, &max_value);
207
208 return (min_cmp == CmpGT || min_cmp == CmpEQ) && (max_cmp == CmpLT || max_cmp == CmpEQ);
209}
210
211void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bit_count, bool is_big_endian) {
212 if (bit_count == 0)
213 return;
214
215 BigInt twos_comp = {0};
216 to_twos_complement(&twos_comp, big_int, bit_count);
217
218 const uint64_t *twos_comp_digits = bigint_ptr(&twos_comp);
219
220 size_t bits_in_last_digit = bit_count % 64;
221 size_t bytes_in_last_digit = (bits_in_last_digit + 7) / 8;
222 size_t unwritten_byte_count = 8 - bytes_in_last_digit;
223
224 if (is_big_endian) {
225 size_t last_digit_index = (bit_count - 1) / 64;
226 size_t digit_index = last_digit_index;
227 size_t buf_index = 0;
228 for (;;) {
229 uint64_t x = (digit_index < twos_comp.digit_count) ? twos_comp_digits[digit_index] : 0;
230
231 for (size_t byte_index = 7;;) {
232 uint8_t byte = x & 0xff;
233 if (digit_index == last_digit_index) {
234 buf[buf_index + byte_index - unwritten_byte_count] = byte;
235 if (byte_index == unwritten_byte_count) break;
236 } else {
237 buf[buf_index + byte_index] = byte;
238 }
239
240 if (byte_index == 0) break;
241 byte_index -= 1;
242 x >>= 8;
243 }
244
245 if (digit_index == 0) break;
246 digit_index -= 1;
247 if (digit_index == last_digit_index) {
248 buf_index += bytes_in_last_digit;
249 } else {
250 buf_index += 8;
251 }
252 }
253 } else {
254 size_t digit_count = (bit_count + 63) / 64;
255 size_t buf_index = 0;
256 for (size_t digit_index = 0; digit_index < digit_count; digit_index += 1) {
257 uint64_t x = (digit_index < twos_comp.digit_count) ? twos_comp_digits[digit_index] : 0;
258
259 for (size_t byte_index = 0; byte_index < 8; byte_index += 1) {
260 uint8_t byte = x & 0xff;
261 buf[buf_index] = byte;
262 buf_index += 1;
263 if (buf_index >= unwritten_byte_count) {
264 break;
265 }
266 x >>= 8;
267 }
268 }
269 }
270}
271
272
273void bigint_read_twos_complement(BigInt *dest, const uint8_t *buf, size_t bit_count, bool is_big_endian,
274 bool is_signed)
275{
276 if (bit_count == 0) {
277 bigint_init_unsigned(dest, 0);
278 return;
279 }
280
281 dest->digit_count = (bit_count + 63) / 64;
282 uint64_t *digits;
283 if (dest->digit_count == 1) {
284 digits = &dest->data.digit;
285 } else {
286 digits = allocate_nonzero<uint64_t>(dest->digit_count);
287 dest->data.digits = digits;
288 }
289
290 size_t bits_in_last_digit = bit_count % 64;
291 if (bits_in_last_digit == 0) {
292 bits_in_last_digit = 64;
293 }
294 size_t bytes_in_last_digit = (bits_in_last_digit + 7) / 8;
295 size_t unread_byte_count = 8 - bytes_in_last_digit;
296
297 if (is_big_endian) {
298 size_t buf_index = 0;
299 uint64_t digit = 0;
300 for (size_t byte_index = unread_byte_count; byte_index < 8; byte_index += 1) {
301 uint8_t byte = buf[buf_index];
302 buf_index += 1;
303 digit <<= 8;
304 digit |= byte;
305 }
306 digits[dest->digit_count - 1] = digit;
307 for (size_t digit_index = 1; digit_index < dest->digit_count; digit_index += 1) {
308 digit = 0;
309 for (size_t byte_index = 0; byte_index < 8; byte_index += 1) {
310 uint8_t byte = buf[buf_index];
311 buf_index += 1;
312 digit <<= 8;
313 digit |= byte;
314 }
315 digits[dest->digit_count - 1 - digit_index] = digit;
316 }
317 } else {
318 size_t buf_index = 0;
319 for (size_t digit_index = 0; digit_index < dest->digit_count; digit_index += 1) {
320 uint64_t digit = 0;
321 size_t end_byte_index = (digit_index == dest->digit_count - 1) ? bytes_in_last_digit : 8;
322 for (size_t byte_index = 0; byte_index < end_byte_index; byte_index += 1) {
323 uint64_t byte = buf[buf_index];
324 buf_index += 1;
325
326 digit |= byte << (8 * byte_index);
327 }
328 digits[digit_index] = digit;
329 }
330 }
331
332 if (is_signed) {
333 bigint_normalize(dest);
334 BigInt tmp = {0};
335 bigint_init_bigint(&tmp, dest);
336 from_twos_complement(dest, &tmp, bit_count, true);
337 } else {
338 dest->is_negative = false;
339 bigint_normalize(dest);
340 }
341}
342
343static bool add_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
344 return __builtin_uaddll_overflow((unsigned long long)op1, (unsigned long long)op2,
345 (unsigned long long *)result);
346}
347
348static bool sub_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
349 return __builtin_usubll_overflow((unsigned long long)op1, (unsigned long long)op2,
350 (unsigned long long *)result);
351}
352
353static bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
354 return __builtin_umulll_overflow((unsigned long long)op1, (unsigned long long)op2,
355 (unsigned long long *)result);
356}
357
358void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) {
359 if (op1->digit_count == 0) {
360 return bigint_init_bigint(dest, op2);
361 }
362 if (op2->digit_count == 0) {
363 return bigint_init_bigint(dest, op1);
364 }
365 if (op1->is_negative == op2->is_negative) {
366 dest->is_negative = op1->is_negative;
367
368 const uint64_t *op1_digits = bigint_ptr(op1);
369 const uint64_t *op2_digits = bigint_ptr(op2);
370 uint64_t overflow = add_u64_overflow(op1_digits[0], op2_digits[0], &dest->data.digit);
371 if (overflow == 0 && op1->digit_count == 1 && op2->digit_count == 1) {
372 dest->digit_count = 1;
373 bigint_normalize(dest);
374 return;
375 }
376 // TODO this code path is untested
377 size_t i = 1;
378 uint64_t first_digit = dest->data.digit;
379 dest->data.digits = allocate_nonzero<uint64_t>(max(op1->digit_count, op2->digit_count) + 1);
380 dest->data.digits[0] = first_digit;
381
382 for (;;) {
383 bool found_digit = false;
384 uint64_t x = overflow;
385 overflow = 0;
386
387 if (i < op1->digit_count) {
388 found_digit = true;
389 uint64_t digit = op1_digits[i];
390 overflow += add_u64_overflow(x, digit, &x);
391 }
392
393 if (i < op2->digit_count) {
394 found_digit = true;
395 uint64_t digit = op2_digits[i];
396 overflow += add_u64_overflow(x, digit, &x);
397 }
398
399 dest->data.digits[i] = x;
400 x += 1;
401
402 if (!found_digit) {
403 break;
404 }
405 }
406 if (overflow > 0) {
407 dest->data.digits[i] = overflow;
408 }
409 bigint_normalize(dest);
410 return;
411 }
412 const BigInt *op_pos;
413 const BigInt *op_neg;
414 if (op1->is_negative) {
415 op_neg = op1;
416 op_pos = op2;
417 } else {
418 op_pos = op1;
419 op_neg = op2;
420 }
421
422 BigInt op_neg_abs = {0};
423 bigint_negate(&op_neg_abs, op_neg);
424 const BigInt *bigger_op;
425 const BigInt *smaller_op;
426 switch (bigint_cmp(op_pos, &op_neg_abs)) {
427 case CmpEQ:
428 bigint_init_unsigned(dest, 0);
429 return;
430 case CmpLT:
431 bigger_op = &op_neg_abs;
432 smaller_op = op_pos;
433 dest->is_negative = true;
434 break;
435 case CmpGT:
436 bigger_op = op_pos;
437 smaller_op = &op_neg_abs;
438 dest->is_negative = false;
439 break;
440 }
441 const uint64_t *bigger_op_digits = bigint_ptr(bigger_op);
442 const uint64_t *smaller_op_digits = bigint_ptr(smaller_op);
443 uint64_t overflow = sub_u64_overflow(bigger_op_digits[0], smaller_op_digits[0], &dest->data.digit);
444 if (overflow == 0 && bigger_op->digit_count == 1 && smaller_op->digit_count == 1) {
445 dest->digit_count = 1;
446 bigint_normalize(dest);
447 return;
448 }
449 uint64_t first_digit = dest->data.digit;
450 dest->data.digits = allocate_nonzero<uint64_t>(bigger_op->digit_count);
451 dest->data.digits[0] = first_digit;
452 size_t i = 1;
453
454 for (;;) {
455 bool found_digit = false;
456 uint64_t x = bigger_op_digits[i];
457 uint64_t prev_overflow = overflow;
458 overflow = 0;
459
460 if (i < smaller_op->digit_count) {
461 found_digit = true;
462 uint64_t digit = smaller_op_digits[i];
463 overflow += sub_u64_overflow(x, digit, &x);
464 }
465 if (sub_u64_overflow(x, prev_overflow, &x)) {
466 found_digit = true;
467 overflow += 1;
468 }
469 dest->data.digits[i] = x;
470 i += 1;
471
472 if (!found_digit)
473 break;
474 }
475 assert(overflow == 0);
476 dest->digit_count = i;
477 bigint_normalize(dest);
478}
479
480void bigint_add_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed) {
481 BigInt unwrapped = {0};
482 bigint_add(&unwrapped, op1, op2);
483 bigint_truncate(dest, &unwrapped, bit_count, is_signed);
484}
485
486void bigint_sub(BigInt *dest, const BigInt *op1, const BigInt *op2) {
487 BigInt op2_negated = {0};
488 bigint_negate(&op2_negated, op2);
489 return bigint_add(dest, op1, &op2_negated);
490}
491
492void bigint_sub_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed) {
493 BigInt op2_negated = {0};
494 bigint_negate(&op2_negated, op2);
495 return bigint_add_wrap(dest, op1, &op2_negated, bit_count, is_signed);
496}
497
498static void mul_overflow(uint64_t x, uint64_t y, uint64_t *result, uint64_t *carry) {
499 if (!mul_u64_overflow(x, y, result)) {
500 *carry = 0;
501 return;
502 }
503 zig_panic("TODO bigint_mul with big numbers");
504
505 //unsigned __int128 big_x = x;
506 //unsigned __int128 big_y = y;
507 //unsigned __int128 big_result = big_x * big_y;
508 //*carry = big_result >> 64;
509}
510
511void bigint_mul(BigInt *dest, const BigInt *op1, const BigInt *op2) {
512 if (op1->digit_count == 0 || op2->digit_count == 0) {
513 return bigint_init_unsigned(dest, 0);
514 }
515 const uint64_t *op1_digits = bigint_ptr(op1);
516 const uint64_t *op2_digits = bigint_ptr(op2);
517
518 uint64_t carry;
519 mul_overflow(op1_digits[0], op2_digits[0], &dest->data.digit, &carry);
520 if (carry == 0 && op1->digit_count == 1 && op2->digit_count == 1) {
521 dest->is_negative = (op1->is_negative != op2->is_negative);
522 dest->digit_count = 1;
523 bigint_normalize(dest);
524 return;
525 }
526 zig_panic("TODO bigint_mul with big numbers");
527}
528
529void bigint_mul_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed) {
530 BigInt unwrapped = {0};
531 bigint_mul(&unwrapped, op1, op2);
532 bigint_truncate(dest, &unwrapped, bit_count, is_signed);
533}
534
535void bigint_div_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2) {
536 assert(op2->digit_count != 0); // division by zero
537 if (op1->digit_count == 0) {
538 bigint_init_unsigned(dest, 0);
539 return;
540 }
541 if (op1->digit_count != 1 || op2->digit_count != 1) {
542 zig_panic("TODO bigint div_trunc with >1 digits");
543 }
544 const uint64_t *op1_digits = bigint_ptr(op1);
545 const uint64_t *op2_digits = bigint_ptr(op2);
546 dest->data.digit = op1_digits[0] / op2_digits[0];
547 dest->digit_count = 1;
548 dest->is_negative = op1->is_negative != op2->is_negative;
549 bigint_normalize(dest);
550}
551
552void bigint_div_floor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
553 if (op1->is_negative != op2->is_negative) {
554 bigint_div_trunc(dest, op1, op2);
555 BigInt mult_again = {0};
556 bigint_mul(&mult_again, dest, op2);
557 mult_again.is_negative = op1->is_negative;
558 if (bigint_cmp(&mult_again, op1) != CmpEQ) {
559 BigInt tmp = {0};
560 bigint_init_bigint(&tmp, dest);
561 BigInt neg_one = {0};
562 bigint_init_signed(&neg_one, -1);
563 bigint_add(dest, &tmp, &neg_one);
564 }
565 bigint_normalize(dest);
566 } else {
567 bigint_div_trunc(dest, op1, op2);
568 }
569}
570
571void bigint_rem(BigInt *dest, const BigInt *op1, const BigInt *op2) {
572 assert(op2->digit_count != 0); // division by zero
573 if (op1->digit_count == 0) {
574 bigint_init_unsigned(dest, 0);
575 return;
576 }
577 const uint64_t *op1_digits = bigint_ptr(op1);
578 const uint64_t *op2_digits = bigint_ptr(op2);
579 if (op2->digit_count == 2 && op2_digits[0] == 0 && op2_digits[1] == 1) {
580 // special case this divisor
581 bigint_init_unsigned(dest, op1_digits[0]);
582 dest->is_negative = op1->is_negative;
583 bigint_normalize(dest);
584 return;
585 }
586 if (op1->digit_count != 1 || op2->digit_count != 1) {
587 zig_panic("TODO bigint rem with >1 digits");
588 }
589 dest->data.digit = op1_digits[0] % op2_digits[0];
590 dest->digit_count = 1;
591 dest->is_negative = op1->is_negative;
592 bigint_normalize(dest);
593}
594
595void bigint_mod(BigInt *dest, const BigInt *op1, const BigInt *op2) {
596 if (op1->is_negative) {
597 BigInt first_rem;
598 bigint_rem(&first_rem, op1, op2);
599 first_rem.is_negative = !op2->is_negative;
600 BigInt op2_minus_rem;
601 bigint_add(&op2_minus_rem, op2, &first_rem);
602 bigint_rem(dest, &op2_minus_rem, op2);
603 dest->is_negative = false;
604 } else {
605 bigint_rem(dest, op1, op2);
606 dest->is_negative = false;
607 }
608}
609
610void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) {
611 if (op1->digit_count == 0) {
612 return bigint_init_bigint(dest, op2);
613 }
614 if (op2->digit_count == 0) {
615 return bigint_init_bigint(dest, op1);
616 }
617 if (op1->is_negative || op2->is_negative) {
618 // TODO this code path is untested
619 size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
620
621 BigInt twos_comp_op1 = {0};
622 to_twos_complement(&twos_comp_op1, op1, big_bit_count);
623
624 BigInt twos_comp_op2 = {0};
625 to_twos_complement(&twos_comp_op2, op2, big_bit_count);
626
627 BigInt twos_comp_dest = {0};
628 bigint_or(&twos_comp_dest, &twos_comp_op1, &twos_comp_op2);
629
630 from_twos_complement(dest, &twos_comp_dest, big_bit_count, true);
631 } else {
632 dest->is_negative = false;
633 const uint64_t *op1_digits = bigint_ptr(op1);
634 const uint64_t *op2_digits = bigint_ptr(op2);
635 if (op1->digit_count == 1 && op2->digit_count == 1) {
636 dest->digit_count = 1;
637 dest->data.digit = op1_digits[0] | op2_digits[0];
638 bigint_normalize(dest);
639 return;
640 }
641 // TODO this code path is untested
642 uint64_t first_digit = dest->data.digit;
643 dest->digit_count = max(op1->digit_count, op2->digit_count);
644 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
645 dest->data.digits[0] = first_digit;
646 size_t i = 1;
647 for (; i < dest->digit_count; i += 1) {
648 uint64_t digit = 0;
649 if (i < op1->digit_count) {
650 digit |= op1_digits[i];
651 }
652 if (i < op2->digit_count) {
653 digit |= op2_digits[i];
654 }
655 dest->data.digits[i] = digit;
656 }
657 bigint_normalize(dest);
658 }
659}
660
661void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) {
662 if (op1->digit_count == 0 || op2->digit_count == 0) {
663 return bigint_init_unsigned(dest, 0);
664 }
665 if (op1->is_negative || op2->is_negative) {
666 // TODO this code path is untested
667 size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
668
669 BigInt twos_comp_op1 = {0};
670 to_twos_complement(&twos_comp_op1, op1, big_bit_count);
671
672 BigInt twos_comp_op2 = {0};
673 to_twos_complement(&twos_comp_op2, op2, big_bit_count);
674
675 BigInt twos_comp_dest = {0};
676 bigint_and(&twos_comp_dest, &twos_comp_op1, &twos_comp_op2);
677
678 from_twos_complement(dest, &twos_comp_dest, big_bit_count, true);
679 } else {
680 dest->is_negative = false;
681 const uint64_t *op1_digits = bigint_ptr(op1);
682 const uint64_t *op2_digits = bigint_ptr(op2);
683 if (op1->digit_count == 1 && op2->digit_count == 1) {
684 dest->digit_count = 1;
685 dest->data.digit = op1_digits[0] & op2_digits[0];
686 bigint_normalize(dest);
687 return;
688 }
689 // TODO this code path is untested
690 uint64_t first_digit = dest->data.digit;
691 dest->digit_count = max(op1->digit_count, op2->digit_count);
692 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
693 dest->data.digits[0] = first_digit;
694 size_t i = 1;
695 for (; i < op1->digit_count && i < op2->digit_count; i += 1) {
696 dest->data.digits[i] = op1_digits[i] & op2_digits[i];
697 }
698 for (; i < dest->digit_count; i += 1) {
699 dest->data.digits[i] = 0;
700 }
701 bigint_normalize(dest);
702 }
703}
704
705void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
706 if (op1->is_negative || op2->is_negative) {
707 // TODO this code path is untested
708 size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
709
710 BigInt twos_comp_op1 = {0};
711 to_twos_complement(&twos_comp_op1, op1, big_bit_count);
712
713 BigInt twos_comp_op2 = {0};
714 to_twos_complement(&twos_comp_op2, op2, big_bit_count);
715
716 BigInt twos_comp_dest = {0};
717 bigint_xor(&twos_comp_dest, &twos_comp_op1, &twos_comp_op2);
718
719 from_twos_complement(dest, &twos_comp_dest, big_bit_count, true);
720 } else {
721 dest->is_negative = false;
722 const uint64_t *op1_digits = bigint_ptr(op1);
723 const uint64_t *op2_digits = bigint_ptr(op2);
724 if (op1->digit_count == 1 && op2->digit_count == 1) {
725 dest->digit_count = 1;
726 dest->data.digit = op1_digits[0] ^ op2_digits[0];
727 bigint_normalize(dest);
728 return;
729 }
730 // TODO this code path is untested
731 uint64_t first_digit = dest->data.digit;
732 dest->digit_count = max(op1->digit_count, op2->digit_count);
733 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
734 dest->data.digits[0] = first_digit;
735 size_t i = 1;
736 for (; i < op1->digit_count && i < op2->digit_count; i += 1) {
737 dest->data.digits[i] = op1_digits[i] ^ op2_digits[i];
738 }
739 for (; i < dest->digit_count; i += 1) {
740 if (i < op1->digit_count) {
741 dest->data.digits[i] = op1_digits[i];
742 }
743 if (i < op2->digit_count) {
744 dest->data.digits[i] = op2_digits[i];
745 }
746 }
747 bigint_normalize(dest);
748 }
749}
750
751void bigint_shl(BigInt *dest, const BigInt *op1, const BigInt *op2) {
752 assert(!op2->is_negative);
753
754 if (op2->digit_count == 0) {
755 bigint_init_bigint(dest, op1);
756 return;
757 }
758
759 if (op1->digit_count == 0) {
760 bigint_init_unsigned(dest, 0);
761 return;
762 }
763
764 if (op2->digit_count != 1) {
765 zig_panic("TODO shift left by amount greater than 64 bit integer");
766 }
767
768 const uint64_t *op1_digits = bigint_ptr(op1);
769 uint64_t shift_amt = bigint_as_unsigned(op2);
770
771 if (op1->digit_count == 1) {
772 dest->data.digit = op1_digits[0] << shift_amt;
773 if (dest->data.digit > op1_digits[0]) {
774 dest->digit_count = 1;
775 dest->is_negative = op1->is_negative;
776 return;
777 }
778 }
779
780 uint64_t digit_shift_count = shift_amt / 64;
781 uint64_t leftover_shift_count = shift_amt % 64;
782
783 dest->data.digits = allocate<uint64_t>(op1->digit_count + digit_shift_count + 1);
784 dest->digit_count = digit_shift_count;
785 uint64_t carry = 0;
786 for (size_t i = 0; i < op1->digit_count; i += 1) {
787 uint64_t digit = op1_digits[i];
788 dest->data.digits[dest->digit_count] = carry | (digit << leftover_shift_count);
789 dest->digit_count += 1;
790 if (leftover_shift_count > 0) {
791 carry = digit >> (64 - leftover_shift_count);
792 } else {
793 carry = 0;
794 }
795 }
796 dest->data.digits[dest->digit_count] = carry;
797 dest->digit_count += 1;
798 dest->is_negative = op1->is_negative;
799 bigint_normalize(dest);
800}
801
802void bigint_shl_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed) {
803 BigInt unwrapped = {0};
804 bigint_shl(&unwrapped, op1, op2);
805 bigint_truncate(dest, &unwrapped, bit_count, is_signed);
806}
807
808void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) {
809 assert(!op2->is_negative);
810
811 if (op1->digit_count == 0) {
812 return bigint_init_unsigned(dest, 0);
813 }
814
815 if (op2->digit_count == 0) {
816 return bigint_init_bigint(dest, op1);
817 }
818
819 if (op2->digit_count != 1) {
820 zig_panic("TODO shift right by amount greater than 64 bit integer");
821 }
822
823 const uint64_t *op1_digits = bigint_ptr(op1);
824 uint64_t shift_amt = bigint_as_unsigned(op2);
825
826 if (op1->digit_count == 1) {
827 dest->data.digit = op1_digits[0] >> shift_amt;
828 dest->digit_count = 1;
829 dest->is_negative = op1->is_negative;
830 bigint_normalize(dest);
831 return;
832 }
833
834 // TODO this code path is untested
835 size_t digit_shift_count = shift_amt / 64;
836 size_t leftover_shift_count = shift_amt % 64;
837
838 if (digit_shift_count >= op1->digit_count) {
839 return bigint_init_unsigned(dest, 0);
840 }
841
842 dest->digit_count = op1->digit_count - digit_shift_count;
843 dest->data.digits = allocate<uint64_t>(dest->digit_count);
844 uint64_t carry = 0;
845 for (size_t op_digit_index = op1->digit_count - 1;;) {
846 uint64_t digit = op1_digits[op_digit_index];
847 size_t dest_digit_index = op_digit_index - digit_shift_count;
848 dest->data.digits[dest_digit_index] = carry | (digit >> leftover_shift_count);
849 carry = (0xffffffffffffffffULL << leftover_shift_count) & digit;
850
851 if (dest_digit_index == 0) { break; }
852 op_digit_index -= 1;
853 }
854 dest->is_negative = op1->is_negative;
855 bigint_normalize(dest);
856}
857
858void bigint_negate(BigInt *dest, const BigInt *op) {
859 bigint_init_bigint(dest, op);
860 dest->is_negative = !dest->is_negative;
861 bigint_normalize(dest);
862}
863
864void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count) {
865 BigInt zero;
866 bigint_init_unsigned(&zero, 0);
867 bigint_sub_wrap(dest, &zero, op, bit_count, true);
868}
869
870void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) {
871 if (bit_count == 0) {
872 bigint_init_unsigned(dest, 0);
873 return;
874 }
875
876 if (is_signed) {
877 BigInt twos_comp = {0};
878 to_twos_complement(&twos_comp, op, bit_count);
879
880 BigInt inverted = {0};
881 bigint_not(&inverted, &twos_comp, bit_count, false);
882
883 from_twos_complement(dest, &inverted, bit_count, true);
884 return;
885 }
886
887 assert(!op->is_negative);
888
889 dest->is_negative = false;
890 const uint64_t *op_digits = bigint_ptr(op);
891 if (bit_count <= 64) {
892 dest->digit_count = 1;
893 if (op->digit_count == 0) {
894 if (bit_count == 64) {
895 dest->data.digit = UINT64_MAX;
896 } else {
897 dest->data.digit = (1ULL << bit_count) - 1;
898 }
899 } else if (op->digit_count == 1) {
900 dest->data.digit = ~op_digits[0];
901 if (bit_count != 64) {
902 uint64_t mask = (1ULL << bit_count) - 1;
903 dest->data.digit &= mask;
904 }
905 }
906 bigint_normalize(dest);
907 return;
908 }
909 // TODO this code path is untested
910 dest->digit_count = bit_count / 64;
911 assert(dest->digit_count >= op->digit_count);
912 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
913 size_t i = 0;
914 for (; i < op->digit_count; i += 1) {
915 dest->data.digits[i] = ~op_digits[i];
916 }
917 for (; i < dest->digit_count; i += 1) {
918 dest->data.digits[i] = 0xffffffffffffffffULL;
919 }
920 size_t digit_index = dest->digit_count - (bit_count / 64) - 1;
921 size_t digit_bit_index = bit_count % 64;
922 if (digit_index < dest->digit_count) {
923 uint64_t mask = (1ULL << digit_bit_index) - 1;
924 dest->data.digits[digit_index] &= mask;
925 }
926 bigint_normalize(dest);
927}
928
929void bigint_truncate(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) {
930 BigInt twos_comp;
931 to_twos_complement(&twos_comp, op, bit_count);
932 from_twos_complement(dest, &twos_comp, bit_count, is_signed);
933}
934
935Cmp bigint_cmp(const BigInt *op1, const BigInt *op2) {
936 if (op1->is_negative && !op2->is_negative) {
937 return CmpLT;
938 } else if (!op1->is_negative && op2->is_negative) {
939 return CmpGT;
940 } else if (op1->digit_count > op2->digit_count) {
941 return op1->is_negative ? CmpLT : CmpGT;
942 } else if (op2->digit_count > op1->digit_count) {
943 return op1->is_negative ? CmpGT : CmpLT;
944 } else if (op1->digit_count == 0) {
945 return CmpEQ;
946 }
947 const uint64_t *op1_digits = bigint_ptr(op1);
948 const uint64_t *op2_digits = bigint_ptr(op2);
949 for (size_t i = op1->digit_count - 1; ;) {
950 uint64_t op1_digit = op1_digits[i];
951 uint64_t op2_digit = op2_digits[i];
952
953 if (op1_digit > op2_digit) {
954 return op1->is_negative ? CmpLT : CmpGT;
955 }
956 if (op1_digit < op2_digit) {
957 return op1->is_negative ? CmpGT : CmpLT;
958 }
959
960 if (i == 0) {
961 return CmpEQ;
962 }
963 i -= 1;
964 }
965}
966
967void bigint_write_buf(Buf *buf, const BigInt *op, uint64_t base) {
968 if (op->digit_count == 0) {
969 buf_append_char(buf, '0');
970 return;
971 }
972 if (op->is_negative) {
973 buf_append_char(buf, '-');
974 }
975 if (op->digit_count == 1 && base == 10) {
976 buf_appendf(buf, "%" ZIG_PRI_u64, op->data.digit);
977 return;
978 }
979 // TODO this code path is untested
980 size_t first_digit_index = buf_len(buf);
981
982 BigInt digit_bi = {0};
983 BigInt a1 = {0};
984 BigInt a2 = {0};
985
986 BigInt *a = &a1;
987 BigInt *other_a = &a2;
988 bigint_init_bigint(a, op);
989
990 BigInt base_bi = {0};
991 bigint_init_unsigned(&base_bi, 10);
992
993 for (;;) {
994 bigint_rem(&digit_bi, a, &base_bi);
995 uint8_t digit = bigint_as_unsigned(&digit_bi);
996 buf_append_char(buf, digit_to_char(digit, false));
997 bigint_div_trunc(other_a, a, &base_bi);
998 {
999 BigInt *tmp = a;
1000 a = other_a;
1001 other_a = tmp;
1002 }
1003 if (bigint_cmp_zero(a) == CmpEQ) {
1004 break;
1005 }
1006 }
1007
1008 // reverse
1009 for (size_t i = first_digit_index; i < buf_len(buf); i += 1) {
1010 size_t other_i = buf_len(buf) + first_digit_index - i - 1;
1011 uint8_t tmp = buf_ptr(buf)[i];
1012 buf_ptr(buf)[i] = buf_ptr(buf)[other_i];
1013 buf_ptr(buf)[other_i] = tmp;
1014 }
1015}
1016
1017size_t bigint_ctz(const BigInt *bi, size_t bit_count) {
1018 if (bit_count == 0)
1019 return 0;
1020 if (bi->digit_count == 0)
1021 return bit_count;
1022
1023 BigInt twos_comp = {0};
1024 to_twos_complement(&twos_comp, bi, bit_count);
1025
1026 size_t count = 0;
1027 for (size_t i = 0; i < bit_count; i += 1) {
1028 if (bit_at_index(&twos_comp, i))
1029 return count;
1030 count += 1;
1031 }
1032 return count;
1033}
1034
1035size_t bigint_clz(const BigInt *bi, size_t bit_count) {
1036 if (bi->is_negative || bit_count == 0)
1037 return 0;
1038 if (bi->digit_count == 0)
1039 return bit_count;
1040
1041 size_t count = 0;
1042 for (size_t i = bit_count - 1;;) {
1043 if (bit_at_index(bi, i))
1044 return count;
1045 count += 1;
1046
1047 if (i == 0) break;
1048 i -= 1;
1049 }
1050 return count;
1051}
1052
1053uint64_t bigint_as_unsigned(const BigInt *bigint) {
1054 assert(!bigint->is_negative);
1055 if (bigint->digit_count == 0) {
1056 return 0;
1057 } else if (bigint->digit_count == 1) {
1058 return bigint->data.digit;
1059 } else {
1060 zig_unreachable();
1061 }
1062}
1063
1064int64_t bigint_as_signed(const BigInt *bigint) {
1065 if (bigint->digit_count == 0) {
1066 return 0;
1067 } else if (bigint->digit_count == 1) {
1068 if (bigint->is_negative) {
1069 // TODO this code path is untested
1070 if (bigint->data.digit <= 9223372036854775808ULL) {
1071 return (-((int64_t)(bigint->data.digit - 1))) - 1;
1072 } else {
1073 zig_unreachable();
1074 }
1075 } else {
1076 return bigint->data.digit;
1077 }
1078 } else {
1079 zig_unreachable();
1080 }
1081}
1082
1083Cmp bigint_cmp_zero(const BigInt *op) {
1084 if (op->digit_count == 0) {
1085 return CmpEQ;
1086 }
1087 return op->is_negative ? CmpLT : CmpGT;
1088}
src/bigint.hpp created+90
...@@ -0,0 +1,90 @@
1/*
2 * Copyright (c) 2017 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_BIGINT_HPP
9#define ZIG_BIGINT_HPP
10
11#include <stdint.h>
12#include <stddef.h>
13
14struct BigInt {
15 size_t digit_count;
16 union {
17 uint64_t digit;
18 uint64_t *digits; // Least significant digit first
19 } data;
20 bool is_negative;
21};
22
23struct Buf;
24struct BigFloat;
25
26enum Cmp {
27 CmpLT,
28 CmpGT,
29 CmpEQ,
30};
31
32void bigint_init_unsigned(BigInt *dest, uint64_t x);
33void bigint_init_signed(BigInt *dest, int64_t x);
34void bigint_init_bigint(BigInt *dest, const BigInt *src);
35void bigint_init_bigfloat(BigInt *dest, const BigFloat *op);
36
37// panics if number won't fit
38uint64_t bigint_as_unsigned(const BigInt *bigint);
39int64_t bigint_as_signed(const BigInt *bigint);
40
41static inline const uint64_t *bigint_ptr(const BigInt *bigint) {
42 if (bigint->digit_count == 1) {
43 return &bigint->data.digit;
44 } else {
45 return bigint->data.digits;
46 }
47}
48
49bool bigint_fits_in_bits(const BigInt *bn, size_t bit_count, bool is_signed);
50void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bit_count, bool is_big_endian);
51void bigint_read_twos_complement(BigInt *dest, const uint8_t *buf, size_t bit_count, bool is_big_endian,
52 bool is_signed);
53void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2);
54void bigint_add_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
55void bigint_sub(BigInt *dest, const BigInt *op1, const BigInt *op2);
56void bigint_sub_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
57void bigint_mul(BigInt *dest, const BigInt *op1, const BigInt *op2);
58void bigint_mul_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
59void bigint_div_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2);
60void bigint_div_floor(BigInt *dest, const BigInt *op1, const BigInt *op2);
61void bigint_rem(BigInt *dest, const BigInt *op1, const BigInt *op2);
62void bigint_mod(BigInt *dest, const BigInt *op1, const BigInt *op2);
63
64void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2);
65void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2);
66void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2);
67
68void bigint_shl(BigInt *dest, const BigInt *op1, const BigInt *op2);
69void bigint_shl_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed);
70void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2);
71
72void bigint_negate(BigInt *dest, const BigInt *op);
73void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count);
74void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);
75void bigint_truncate(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);
76
77Cmp bigint_cmp(const BigInt *op1, const BigInt *op2);
78
79void bigint_write_buf(Buf *buf, const BigInt *op, uint64_t base);
80
81size_t bigint_ctz(const BigInt *bi, size_t bit_count);
82size_t bigint_clz(const BigInt *bi, size_t bit_count);
83
84size_t bigint_bits_needed(const BigInt *op);
85
86
87// convenience functions
88Cmp bigint_cmp_zero(const BigInt *op);
89
90#endif
src/bignum.cpp deleted-535
...@@ -1,535 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "bignum.hpp"
9#include "buffer.hpp"
10#include "os.hpp"
11
12#include <assert.h>
13#include <math.h>
14#include <inttypes.h>
15
16static void bignum_normalize(BigNum *bn) {
17 assert(bn->kind == BigNumKindInt);
18 if (bn->data.x_uint == 0) {
19 bn->is_negative = false;
20 }
21}
22
23void bignum_init_float(BigNum *dest, double x) {
24 dest->kind = BigNumKindFloat;
25 dest->is_negative = false;
26 dest->data.x_float = x;
27}
28
29void bignum_init_unsigned(BigNum *dest, uint64_t x) {
30 dest->kind = BigNumKindInt;
31 dest->is_negative = false;
32 dest->data.x_uint = x;
33}
34
35void bignum_init_signed(BigNum *dest, int64_t x) {
36 dest->kind = BigNumKindInt;
37 if (x < 0) {
38 dest->is_negative = true;
39 dest->data.x_uint = ((uint64_t)(-(x + 1))) + 1;
40 } else {
41 dest->is_negative = false;
42 dest->data.x_uint = x;
43 }
44}
45
46void bignum_init_bignum(BigNum *dest, BigNum *src) {
47 safe_memcpy(dest, src, 1);
48}
49
50static int u64_log2(uint64_t x) {
51 int result = 0;
52 for (; x != 0; x >>= 1) {
53 result += 1;
54 }
55 return result;
56}
57
58bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed) {
59 assert(bn->kind == BigNumKindInt);
60
61 if (is_signed) {
62 uint64_t max_neg;
63 uint64_t max_pos;
64 if (bit_count < 64) {
65 max_neg = (1ULL << (bit_count - 1));
66 max_pos = max_neg - 1;
67 } else {
68 max_pos = ((uint64_t)INT64_MAX);
69 max_neg = max_pos + 1;
70 }
71 uint64_t max_val = bn->is_negative ? max_neg : max_pos;
72 return bn->data.x_uint <= max_val;
73 } else {
74 if (bn->is_negative) {
75 return bn->data.x_uint == 0;
76 } else {
77 int required_bit_count = u64_log2(bn->data.x_uint);
78 return bit_count >= required_bit_count;
79 }
80 }
81}
82
83void bignum_truncate(BigNum *bn, int bit_count) {
84 assert(bn->kind == BigNumKindInt);
85 // TODO handle case when negative = true
86 if (bit_count < 64) {
87 bn->data.x_uint &= (1LL << bit_count) - 1;
88 }
89}
90
91uint64_t bignum_to_twos_complement(BigNum *bn) {
92 assert(bn->kind == BigNumKindInt);
93
94 if (bn->is_negative) {
95 int64_t x = bn->data.x_uint;
96 return -x;
97 } else {
98 return bn->data.x_uint;
99 }
100}
101
102// returns true if overflow happened
103bool bignum_add(BigNum *dest, BigNum *op1, BigNum *op2) {
104 assert(op1->kind == op2->kind);
105 dest->kind = op1->kind;
106
107 if (dest->kind == BigNumKindFloat) {
108 dest->data.x_float = op1->data.x_float + op2->data.x_float;
109 return false;
110 }
111
112 if (op1->is_negative == op2->is_negative) {
113 dest->is_negative = op1->is_negative;
114 return __builtin_uaddll_overflow(op1->data.x_uint, op2->data.x_uint, &dest->data.x_uint);
115 } else if (!op1->is_negative && op2->is_negative) {
116 if (__builtin_usubll_overflow(op1->data.x_uint, op2->data.x_uint, &dest->data.x_uint)) {
117 dest->data.x_uint = (UINT64_MAX - dest->data.x_uint) + 1;
118 dest->is_negative = true;
119 bignum_normalize(dest);
120 return false;
121 } else {
122 bignum_normalize(dest);
123 return false;
124 }
125 } else {
126 return bignum_add(dest, op2, op1);
127 }
128}
129
130void bignum_negate(BigNum *dest, BigNum *op) {
131 dest->kind = op->kind;
132
133 if (dest->kind == BigNumKindFloat) {
134 dest->data.x_float = -op->data.x_float;
135 } else {
136 dest->data.x_uint = op->data.x_uint;
137 dest->is_negative = !op->is_negative;
138 bignum_normalize(dest);
139 }
140}
141
142void bignum_not(BigNum *dest, BigNum *op, int bit_count, bool is_signed) {
143 assert(op->kind == BigNumKindInt);
144 uint64_t bits = ~bignum_to_twos_complement(op);
145 if (bit_count < 64) {
146 bits &= (1LL << bit_count) - 1;
147 }
148 if (is_signed)
149 bignum_init_signed(dest, bits);
150 else
151 bignum_init_unsigned(dest, bits);
152}
153
154void bignum_cast_to_float(BigNum *dest, BigNum *op) {
155 assert(op->kind == BigNumKindInt);
156 dest->kind = BigNumKindFloat;
157
158 dest->data.x_float = (double)op->data.x_uint;
159
160 if (op->is_negative) {
161 dest->data.x_float = -dest->data.x_float;
162 }
163}
164
165void bignum_cast_to_int(BigNum *dest, BigNum *op) {
166 assert(op->kind == BigNumKindFloat);
167 dest->kind = BigNumKindInt;
168
169 if (op->data.x_float >= 0) {
170 dest->data.x_uint = (unsigned long long)op->data.x_float;
171 dest->is_negative = false;
172 } else {
173 dest->data.x_uint = (unsigned long long)-op->data.x_float;
174 dest->is_negative = true;
175 }
176}
177
178bool bignum_sub(BigNum *dest, BigNum *op1, BigNum *op2) {
179 BigNum op2_negated;
180 bignum_negate(&op2_negated, op2);
181 return bignum_add(dest, op1, &op2_negated);
182}
183
184bool bignum_mul(BigNum *dest, BigNum *op1, BigNum *op2) {
185 assert(op1->kind == op2->kind);
186 dest->kind = op1->kind;
187
188 if (dest->kind == BigNumKindFloat) {
189 dest->data.x_float = op1->data.x_float * op2->data.x_float;
190 return false;
191 }
192
193 if (__builtin_umulll_overflow(op1->data.x_uint, op2->data.x_uint, &dest->data.x_uint)) {
194 return true;
195 }
196
197 dest->is_negative = op1->is_negative != op2->is_negative;
198 bignum_normalize(dest);
199 return false;
200}
201
202bool bignum_div(BigNum *dest, BigNum *op1, BigNum *op2) {
203 assert(op1->kind == op2->kind);
204 dest->kind = op1->kind;
205
206 if (dest->kind == BigNumKindFloat) {
207 dest->data.x_float = op1->data.x_float / op2->data.x_float;
208 } else {
209 return bignum_div_trunc(dest, op1, op2);
210 }
211 return false;
212}
213
214bool bignum_div_trunc(BigNum *dest, BigNum *op1, BigNum *op2) {
215 assert(op1->kind == op2->kind);
216 dest->kind = op1->kind;
217
218 if (dest->kind == BigNumKindFloat) {
219 double result = op1->data.x_float / op2->data.x_float;
220 if (result >= 0) {
221 dest->data.x_float = floor(result);
222 } else {
223 dest->data.x_float = ceil(result);
224 }
225 } else {
226 dest->data.x_uint = op1->data.x_uint / op2->data.x_uint;
227 dest->is_negative = op1->is_negative != op2->is_negative;
228 bignum_normalize(dest);
229 }
230 return false;
231}
232
233bool bignum_div_floor(BigNum *dest, BigNum *op1, BigNum *op2) {
234 assert(op1->kind == op2->kind);
235 dest->kind = op1->kind;
236
237 if (dest->kind == BigNumKindFloat) {
238 dest->data.x_float = floor(op1->data.x_float / op2->data.x_float);
239 } else {
240 if (op1->is_negative != op2->is_negative) {
241 uint64_t result = op1->data.x_uint / op2->data.x_uint;
242 if (result * op2->data.x_uint == op1->data.x_uint) {
243 dest->data.x_uint = result;
244 } else {
245 dest->data.x_uint = result + 1;
246 }
247 dest->is_negative = true;
248 } else {
249 dest->data.x_uint = op1->data.x_uint / op2->data.x_uint;
250 dest->is_negative = false;
251 }
252 }
253 return false;
254}
255
256bool bignum_rem(BigNum *dest, BigNum *op1, BigNum *op2) {
257 assert(op1->kind == op2->kind);
258 dest->kind = op1->kind;
259
260 if (dest->kind == BigNumKindFloat) {
261 dest->data.x_float = fmod(op1->data.x_float, op2->data.x_float);
262 } else {
263 dest->data.x_uint = op1->data.x_uint % op2->data.x_uint;
264 dest->is_negative = op1->is_negative;
265 bignum_normalize(dest);
266 }
267 return false;
268}
269
270bool bignum_mod(BigNum *dest, BigNum *op1, BigNum *op2) {
271 assert(op1->kind == op2->kind);
272 dest->kind = op1->kind;
273
274 if (dest->kind == BigNumKindFloat) {
275 dest->data.x_float = fmod(fmod(op1->data.x_float, op2->data.x_float) + op2->data.x_float, op2->data.x_float);
276 } else {
277 if (op1->is_negative) {
278 dest->data.x_uint = (op2->data.x_uint - op1->data.x_uint % op2->data.x_uint) % op2->data.x_uint;
279 } else {
280 dest->data.x_uint = op1->data.x_uint % op2->data.x_uint;
281 }
282 dest->is_negative = false;
283 bignum_normalize(dest);
284 }
285 return false;
286}
287
288bool bignum_or(BigNum *dest, BigNum *op1, BigNum *op2) {
289 assert(op1->kind == BigNumKindInt);
290 assert(op2->kind == BigNumKindInt);
291
292 assert(!op1->is_negative);
293 assert(!op2->is_negative);
294
295 dest->kind = BigNumKindInt;
296 dest->data.x_uint = op1->data.x_uint | op2->data.x_uint;
297 return false;
298}
299
300bool bignum_and(BigNum *dest, BigNum *op1, BigNum *op2) {
301 assert(op1->kind == BigNumKindInt);
302 assert(op2->kind == BigNumKindInt);
303
304 assert(!op1->is_negative);
305 assert(!op2->is_negative);
306
307 dest->kind = BigNumKindInt;
308 dest->data.x_uint = op1->data.x_uint & op2->data.x_uint;
309 return false;
310}
311
312bool bignum_xor(BigNum *dest, BigNum *op1, BigNum *op2) {
313 assert(op1->kind == BigNumKindInt);
314 assert(op2->kind == BigNumKindInt);
315
316 assert(!op1->is_negative);
317 assert(!op2->is_negative);
318
319 dest->kind = BigNumKindInt;
320 dest->data.x_uint = op1->data.x_uint ^ op2->data.x_uint;
321 return false;
322}
323
324bool bignum_shl(BigNum *dest, BigNum *op1, BigNum *op2) {
325 assert(op1->kind == BigNumKindInt);
326 assert(op2->kind == BigNumKindInt);
327
328 assert(!op1->is_negative);
329 assert(!op2->is_negative);
330
331 dest->kind = BigNumKindInt;
332 dest->data.x_uint = op1->data.x_uint << op2->data.x_uint;
333 return false;
334}
335
336bool bignum_shr(BigNum *dest, BigNum *op1, BigNum *op2) {
337 assert(op1->kind == BigNumKindInt);
338 assert(op2->kind == BigNumKindInt);
339
340 assert(!op1->is_negative);
341 assert(!op2->is_negative);
342
343 dest->kind = BigNumKindInt;
344 dest->data.x_uint = op1->data.x_uint >> op2->data.x_uint;
345 return false;
346}
347
348
349Buf *bignum_to_buf(BigNum *bn) {
350 if (bn->kind == BigNumKindFloat) {
351 return buf_sprintf("%f", bn->data.x_float);
352 } else {
353 const char *neg = bn->is_negative ? "-" : "";
354 return buf_sprintf("%s%" ZIG_PRI_llu "", neg, bn->data.x_uint);
355 }
356}
357
358bool bignum_cmp_eq(BigNum *op1, BigNum *op2) {
359 assert(op1->kind == op2->kind);
360 if (op1->kind == BigNumKindFloat) {
361 return op1->data.x_float == op2->data.x_float;
362 } else {
363 return op1->data.x_uint == op2->data.x_uint &&
364 (op1->is_negative == op2->is_negative || op1->data.x_uint == 0);
365 }
366}
367
368bool bignum_cmp_neq(BigNum *op1, BigNum *op2) {
369 return !bignum_cmp_eq(op1, op2);
370}
371
372bool bignum_cmp_lt(BigNum *op1, BigNum *op2) {
373 return !bignum_cmp_gte(op1, op2);
374}
375
376bool bignum_cmp_gt(BigNum *op1, BigNum *op2) {
377 return !bignum_cmp_lte(op1, op2);
378}
379
380bool bignum_cmp_lte(BigNum *op1, BigNum *op2) {
381 assert(op1->kind == op2->kind);
382 if (op1->kind == BigNumKindFloat) {
383 return (op1->data.x_float <= op2->data.x_float);
384 }
385
386 // assume normalized is_negative
387 if (!op1->is_negative && !op2->is_negative) {
388 return op1->data.x_uint <= op2->data.x_uint;
389 } else if (op1->is_negative && op2->is_negative) {
390 return op1->data.x_uint >= op2->data.x_uint;
391 } else if (op1->is_negative && !op2->is_negative) {
392 return true;
393 } else {
394 return false;
395 }
396}
397
398bool bignum_cmp_gte(BigNum *op1, BigNum *op2) {
399 assert(op1->kind == op2->kind);
400
401 if (op1->kind == BigNumKindFloat) {
402 return (op1->data.x_float >= op2->data.x_float);
403 }
404
405 // assume normalized is_negative
406 if (!op1->is_negative && !op2->is_negative) {
407 return op1->data.x_uint >= op2->data.x_uint;
408 } else if (op1->is_negative && op2->is_negative) {
409 return op1->data.x_uint <= op2->data.x_uint;
410 } else if (op1->is_negative && !op2->is_negative) {
411 return false;
412 } else {
413 return true;
414 }
415}
416
417bool bignum_increment_by_scalar(BigNum *bignum, uint64_t scalar) {
418 assert(bignum->kind == BigNumKindInt);
419 assert(!bignum->is_negative);
420 return __builtin_uaddll_overflow(bignum->data.x_uint, scalar, &bignum->data.x_uint);
421}
422
423bool bignum_multiply_by_scalar(BigNum *bignum, uint64_t scalar) {
424 assert(bignum->kind == BigNumKindInt);
425 assert(!bignum->is_negative);
426 return __builtin_umulll_overflow(bignum->data.x_uint, scalar, &bignum->data.x_uint);
427}
428
429uint32_t bignum_ctz(BigNum *bignum, uint32_t bit_count) {
430 assert(bignum->kind == BigNumKindInt);
431
432 uint64_t x = bignum_to_twos_complement(bignum);
433 uint32_t result = 0;
434 for (uint32_t i = 0; i < bit_count; i += 1) {
435 if ((x & 0x1) != 0)
436 break;
437
438 result += 1;
439 x = x >> 1;
440 }
441 return result;
442}
443
444uint32_t bignum_clz(BigNum *bignum, uint32_t bit_count) {
445 assert(bignum->kind == BigNumKindInt);
446
447 if (bit_count == 0)
448 return 0;
449
450 uint64_t x = bignum_to_twos_complement(bignum);
451 uint64_t mask = ((uint64_t)1) << ((uint64_t)bit_count - 1);
452 uint32_t result = 0;
453 for (uint32_t i = 0; i < bit_count; i += 1) {
454 if ((x & mask) != 0)
455 break;
456
457 result += 1;
458 x = x << 1;
459 }
460 return result;
461}
462
463void bignum_write_twos_complement(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian) {
464 assert(bn->kind == BigNumKindInt);
465 uint64_t x = bignum_to_twos_complement(bn);
466
467 int byte_count = (bit_count + 7) / 8;
468 for (int i = 0; i < byte_count; i += 1) {
469 uint8_t le_byte = (x >> (i * 8)) & 0xff;
470 if (is_big_endian) {
471 buf[byte_count - i - 1] = le_byte;
472 } else {
473 buf[i] = le_byte;
474 }
475 }
476}
477
478void bignum_read_twos_complement(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian, bool is_signed) {
479 int byte_count = (bit_count + 7) / 8;
480
481 uint64_t twos_comp = 0;
482 for (int i = 0; i < byte_count; i += 1) {
483 uint8_t be_byte;
484 if (is_big_endian) {
485 be_byte = buf[i];
486 } else {
487 be_byte = buf[byte_count - i - 1];
488 }
489
490 twos_comp <<= 8;
491 twos_comp |= be_byte;
492 }
493
494 uint8_t be_byte = buf[is_big_endian ? 0 : byte_count - 1];
495 if (is_signed && ((be_byte >> 7) & 0x1) != 0) {
496 bn->is_negative = true;
497 uint64_t mask = 0;
498 for (int i = 0; i < bit_count; i += 1) {
499 mask <<= 1;
500 mask |= 1;
501 }
502 bn->data.x_uint = ((~twos_comp) & mask) + 1;
503 } else {
504 bn->data.x_uint = twos_comp;
505 }
506 bn->kind = BigNumKindInt;
507}
508
509void bignum_write_ieee597(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian) {
510 assert(bn->kind == BigNumKindFloat);
511 if (bit_count == 32) {
512 float f32 = bn->data.x_float;
513 memcpy(buf, &f32, 4);
514 } else if (bit_count == 64) {
515 double f64 = bn->data.x_float;
516 memcpy(buf, &f64, 8);
517 } else {
518 zig_unreachable();
519 }
520}
521
522void bignum_read_ieee597(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian) {
523 bn->kind = BigNumKindFloat;
524 if (bit_count == 32) {
525 float f32;
526 memcpy(&f32, buf, 4);
527 bn->data.x_float = f32;
528 } else if (bit_count == 64) {
529 double f64;
530 memcpy(&f64, buf, 8);
531 bn->data.x_float = f64;
532 } else {
533 zig_unreachable();
534 }
535}
src/bignum.hpp deleted-81
...@@ -1,81 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_BIGNUM_HPP
9#define ZIG_BIGNUM_HPP
10
11#include <stdint.h>
12
13enum BigNumKind {
14 BigNumKindInt,
15 BigNumKindFloat,
16};
17
18struct BigNum {
19 BigNumKind kind;
20 bool is_negative;
21 union {
22 unsigned long long x_uint;
23 double x_float;
24 } data;
25};
26
27void bignum_init_float(BigNum *dest, double x);
28void bignum_init_unsigned(BigNum *dest, uint64_t x);
29void bignum_init_signed(BigNum *dest, int64_t x);
30void bignum_init_bignum(BigNum *dest, BigNum *src);
31
32bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed);
33uint64_t bignum_to_twos_complement(BigNum *bn);
34
35void bignum_write_twos_complement(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian);
36void bignum_write_ieee597(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian);
37void bignum_read_twos_complement(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian, bool is_signed);
38void bignum_read_ieee597(BigNum *bn, uint8_t *buf, int bit_count, bool is_big_endian);
39
40// returns true if overflow happened
41bool bignum_add(BigNum *dest, BigNum *op1, BigNum *op2);
42bool bignum_sub(BigNum *dest, BigNum *op1, BigNum *op2);
43bool bignum_mul(BigNum *dest, BigNum *op1, BigNum *op2);
44bool bignum_div(BigNum *dest, BigNum *op1, BigNum *op2);
45bool bignum_div_trunc(BigNum *dest, BigNum *op1, BigNum *op2);
46bool bignum_div_floor(BigNum *dest, BigNum *op1, BigNum *op2);
47bool bignum_rem(BigNum *dest, BigNum *op1, BigNum *op2);
48bool bignum_mod(BigNum *dest, BigNum *op1, BigNum *op2);
49
50bool bignum_or(BigNum *dest, BigNum *op1, BigNum *op2);
51bool bignum_and(BigNum *dest, BigNum *op1, BigNum *op2);
52bool bignum_xor(BigNum *dest, BigNum *op1, BigNum *op2);
53bool bignum_shl(BigNum *dest, BigNum *op1, BigNum *op2);
54bool bignum_shr(BigNum *dest, BigNum *op1, BigNum *op2);
55
56void bignum_negate(BigNum *dest, BigNum *op);
57void bignum_cast_to_float(BigNum *dest, BigNum *op);
58void bignum_cast_to_int(BigNum *dest, BigNum *op);
59void bignum_not(BigNum *dest, BigNum *op, int bit_count, bool is_signed);
60
61void bignum_truncate(BigNum *dest, int bit_count);
62
63// returns the result of the comparison
64bool bignum_cmp_eq(BigNum *op1, BigNum *op2);
65bool bignum_cmp_neq(BigNum *op1, BigNum *op2);
66bool bignum_cmp_lt(BigNum *op1, BigNum *op2);
67bool bignum_cmp_gt(BigNum *op1, BigNum *op2);
68bool bignum_cmp_lte(BigNum *op1, BigNum *op2);
69bool bignum_cmp_gte(BigNum *op1, BigNum *op2);
70
71// helper functions
72bool bignum_increment_by_scalar(BigNum *bignum, uint64_t scalar);
73bool bignum_multiply_by_scalar(BigNum *bignum, uint64_t scalar);
74
75struct Buf;
76Buf *bignum_to_buf(BigNum *bn);
77
78uint32_t bignum_ctz(BigNum *bignum, uint32_t bit_count);
79uint32_t bignum_clz(BigNum *bignum, uint32_t bit_count);
80
81#endif
src/codegen.cpp+33-19
...@@ -1203,6 +1203,23 @@ enum DivKind {...@@ -1203,6 +1203,23 @@ enum DivKind {
1203 DivKindExact,1203 DivKindExact,
1204};1204};
12051205
1206static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) {
1207 if (bigint->digit_count == 0) {
1208 return LLVMConstNull(type_ref);
1209 }
1210 LLVMValueRef unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref,
1211 bigint->digit_count, bigint_ptr(bigint));
1212 if (bigint->is_negative) {
1213 return LLVMConstNeg(unsigned_val);
1214 } else {
1215 return unsigned_val;
1216 }
1217}
1218
1219static LLVMValueRef bigfloat_to_llvm_const(LLVMTypeRef type_ref, BigFloat *bigfloat) {
1220 return LLVMConstReal(type_ref, bigfloat_to_double(bigfloat));
1221}
1222
1206static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_math,1223static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_math,
1207 LLVMValueRef val1, LLVMValueRef val2,1224 LLVMValueRef val1, LLVMValueRef val2,
1208 TypeTableEntry *type_entry, DivKind div_kind)1225 TypeTableEntry *type_entry, DivKind div_kind)
...@@ -1230,7 +1247,9 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_m...@@ -1230,7 +1247,9 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_m
12301247
1231 if (type_entry->id == TypeTableEntryIdInt && type_entry->data.integral.is_signed) {1248 if (type_entry->id == TypeTableEntryIdInt && type_entry->data.integral.is_signed) {
1232 LLVMValueRef neg_1_value = LLVMConstInt(type_entry->type_ref, -1, true);1249 LLVMValueRef neg_1_value = LLVMConstInt(type_entry->type_ref, -1, true);
1233 LLVMValueRef int_min_value = LLVMConstInt(type_entry->type_ref, min_signed_val(type_entry), true);1250 BigInt int_min_bi = {0};
1251 eval_min_max_value_int(g, type_entry, &int_min_bi, false);
1252 LLVMValueRef int_min_value = bigint_to_llvm_const(type_entry->type_ref, &int_min_bi);
1234 LLVMBasicBlockRef overflow_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowOk");1253 LLVMBasicBlockRef overflow_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowOk");
1235 LLVMBasicBlockRef overflow_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowFail");1254 LLVMBasicBlockRef overflow_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowFail");
1236 LLVMValueRef num_is_int_min = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, int_min_value, "");1255 LLVMValueRef num_is_int_min = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, int_min_value, "");
...@@ -1765,8 +1784,13 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, I...@@ -1765,8 +1784,13 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, I
1765 LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);1784 LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);
1766 LLVMValueRef neq_zero_bit = LLVMBuildICmp(g->builder, LLVMIntNE, target_val, zero, "");1785 LLVMValueRef neq_zero_bit = LLVMBuildICmp(g->builder, LLVMIntNE, target_val, zero, "");
1767 LLVMValueRef ok_bit;1786 LLVMValueRef ok_bit;
1768 uint64_t biggest_possible_err_val = max_unsigned_val(actual_type);1787
1769 if (biggest_possible_err_val < g->error_decls.length) {1788 BigInt biggest_possible_err_val = {0};
1789 eval_min_max_value_int(g, actual_type, &biggest_possible_err_val, true);
1790
1791 if (bigint_fits_in_bits(&biggest_possible_err_val, 64, false) &&
1792 bigint_as_unsigned(&biggest_possible_err_val) < g->error_decls.length)
1793 {
1770 ok_bit = neq_zero_bit;1794 ok_bit = neq_zero_bit;
1771 } else {1795 } else {
1772 LLVMValueRef error_value_count = LLVMConstInt(actual_type->type_ref, g->error_decls.length, false);1796 LLVMValueRef error_value_count = LLVMConstInt(actual_type->type_ref, g->error_decls.length, false);
...@@ -3317,7 +3341,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con...@@ -3317,7 +3341,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
3317 LLVMValueRef int_val = gen_const_val(g, const_val);3341 LLVMValueRef int_val = gen_const_val(g, const_val);
3318 return LLVMConstZExt(int_val, big_int_type_ref);3342 return LLVMConstZExt(int_val, big_int_type_ref);
3319 }3343 }
3320 return LLVMConstInt(big_int_type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
3321 case TypeTableEntryIdFloat:3344 case TypeTableEntryIdFloat:
3322 {3345 {
3323 LLVMValueRef float_val = gen_const_val(g, const_val);3346 LLVMValueRef float_val = gen_const_val(g, const_val);
...@@ -3374,21 +3397,13 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -3374,21 +3397,13 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
3374 switch (type_entry->id) {3397 switch (type_entry->id) {
3375 case TypeTableEntryIdInt:3398 case TypeTableEntryIdInt:
3376 case TypeTableEntryIdEnumTag:3399 case TypeTableEntryIdEnumTag:
3377 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);3400 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
3378 case TypeTableEntryIdPureError:3401 case TypeTableEntryIdPureError:
3379 assert(const_val->data.x_pure_err);3402 assert(const_val->data.x_pure_err);
3380 return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref,3403 return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref,
3381 const_val->data.x_pure_err->value, false);3404 const_val->data.x_pure_err->value, false);
3382 case TypeTableEntryIdFloat:3405 case TypeTableEntryIdFloat:
3383 if (const_val->data.x_bignum.kind == BigNumKindFloat) {3406 return bigfloat_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigfloat);
3384 return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float);
3385 } else {
3386 double x = (double)const_val->data.x_bignum.data.x_uint;
3387 if (const_val->data.x_bignum.is_negative) {
3388 x = -x;
3389 }
3390 return LLVMConstReal(type_entry->type_ref, x);
3391 }
3392 case TypeTableEntryIdBool:3407 case TypeTableEntryIdBool:
3393 if (const_val->data.x_bool) {3408 if (const_val->data.x_bool) {
3394 return LLVMConstAllOnes(LLVMInt1Type());3409 return LLVMConstAllOnes(LLVMInt1Type());
...@@ -3866,7 +3881,7 @@ static void do_code_gen(CodeGen *g) {...@@ -3866,7 +3881,7 @@ static void do_code_gen(CodeGen *g) {
3866 ConstExprValue *const_val = var->value;3881 ConstExprValue *const_val = var->value;
3867 assert(const_val->special != ConstValSpecialRuntime);3882 assert(const_val->special != ConstValSpecialRuntime);
3868 TypeTableEntry *var_type = g->builtin_types.entry_f64;3883 TypeTableEntry *var_type = g->builtin_types.entry_f64;
3869 LLVMValueRef init_val = LLVMConstReal(var_type->type_ref, const_val->data.x_bignum.data.x_float);3884 LLVMValueRef init_val = bigfloat_to_llvm_const(var_type->type_ref, &const_val->data.x_bigfloat);
3870 gen_global_var(g, var, init_val, var_type);3885 gen_global_var(g, var, init_val, var_type);
3871 continue;3886 continue;
3872 }3887 }
...@@ -3875,10 +3890,9 @@ static void do_code_gen(CodeGen *g) {...@@ -3875,10 +3890,9 @@ static void do_code_gen(CodeGen *g) {
3875 // Generate debug info for it but that's it.3890 // Generate debug info for it but that's it.
3876 ConstExprValue *const_val = var->value;3891 ConstExprValue *const_val = var->value;
3877 assert(const_val->special != ConstValSpecialRuntime);3892 assert(const_val->special != ConstValSpecialRuntime);
3878 TypeTableEntry *var_type = const_val->data.x_bignum.is_negative ?3893 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
3879 g->builtin_types.entry_isize : g->builtin_types.entry_usize;3894 TypeTableEntry *var_type = get_int_type(g, const_val->data.x_bigint.is_negative, bits_needed);
3880 LLVMValueRef init_val = LLVMConstInt(var_type->type_ref,3895 LLVMValueRef init_val = bigint_to_llvm_const(var_type->type_ref, &const_val->data.x_bigint);
3881 bignum_to_twos_complement(&const_val->data.x_bignum), false);
3882 gen_global_var(g, var, init_val, var_type);3896 gen_global_var(g, var, init_val, var_type);
3883 continue;3897 continue;
3884 }3898 }
src/ir.cpp+405-300
...@@ -656,16 +656,23 @@ static IrInstruction *ir_build_const_uint(IrBuilder *irb, Scope *scope, AstNode...@@ -656,16 +656,23 @@ static IrInstruction *ir_build_const_uint(IrBuilder *irb, Scope *scope, AstNode
656 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);656 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
657 const_instruction->base.value.type = irb->codegen->builtin_types.entry_num_lit_int;657 const_instruction->base.value.type = irb->codegen->builtin_types.entry_num_lit_int;
658 const_instruction->base.value.special = ConstValSpecialStatic;658 const_instruction->base.value.special = ConstValSpecialStatic;
659 bignum_init_unsigned(&const_instruction->base.value.data.x_bignum, value);659 bigint_init_unsigned(&const_instruction->base.value.data.x_bigint, value);
660 return &const_instruction->base;660 return &const_instruction->base;
661}661}
662662
663static IrInstruction *ir_build_const_bignum(IrBuilder *irb, Scope *scope, AstNode *source_node, BigNum *bignum) {663static IrInstruction *ir_build_const_bigint(IrBuilder *irb, Scope *scope, AstNode *source_node, BigInt *bigint) {
664 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);664 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
665 const_instruction->base.value.type = (bignum->kind == BigNumKindInt) ?665 const_instruction->base.value.type = irb->codegen->builtin_types.entry_num_lit_int;
666 irb->codegen->builtin_types.entry_num_lit_int : irb->codegen->builtin_types.entry_num_lit_float;666 const_instruction->base.value.special = ConstValSpecialStatic;
667 bigint_init_bigint(&const_instruction->base.value.data.x_bigint, bigint);
668 return &const_instruction->base;
669}
670
671static IrInstruction *ir_build_const_bigfloat(IrBuilder *irb, Scope *scope, AstNode *source_node, BigFloat *bigfloat) {
672 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
673 const_instruction->base.value.type = irb->codegen->builtin_types.entry_num_lit_float;
667 const_instruction->base.value.special = ConstValSpecialStatic;674 const_instruction->base.value.special = ConstValSpecialStatic;
668 const_instruction->base.value.data.x_bignum = *bignum;675 bigfloat_init_bigfloat(&const_instruction->base.value.data.x_bigfloat, bigfloat);
669 return &const_instruction->base;676 return &const_instruction->base;
670}677}
671678
...@@ -680,7 +687,7 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, Scope *scope, AstNode...@@ -680,7 +687,7 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, Scope *scope, AstNode
680 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);687 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
681 const_instruction->base.value.type = irb->codegen->builtin_types.entry_usize;688 const_instruction->base.value.type = irb->codegen->builtin_types.entry_usize;
682 const_instruction->base.value.special = ConstValSpecialStatic;689 const_instruction->base.value.special = ConstValSpecialStatic;
683 bignum_init_unsigned(&const_instruction->base.value.data.x_bignum, value);690 bigint_init_unsigned(&const_instruction->base.value.data.x_bigint, value);
684 return &const_instruction->base;691 return &const_instruction->base;
685}692}
686693
...@@ -3687,15 +3694,21 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -3687,15 +3694,21 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)
3687 zig_unreachable();3694 zig_unreachable();
3688}3695}
36893696
3690static IrInstruction *ir_gen_num_lit(IrBuilder *irb, Scope *scope, AstNode *node) {3697static IrInstruction *ir_gen_int_lit(IrBuilder *irb, Scope *scope, AstNode *node) {
3691 assert(node->type == NodeTypeNumberLiteral);3698 assert(node->type == NodeTypeIntLiteral);
3699
3700 return ir_build_const_bigint(irb, scope, node, node->data.int_literal.bigint);
3701}
36923702
3693 if (node->data.number_literal.overflow) {3703static IrInstruction *ir_gen_float_lit(IrBuilder *irb, Scope *scope, AstNode *node) {
3694 add_node_error(irb->codegen, node, buf_sprintf("number literal too large to be represented in any type"));3704 assert(node->type == NodeTypeFloatLiteral);
3705
3706 if (node->data.float_literal.overflow) {
3707 add_node_error(irb->codegen, node, buf_sprintf("float literal too large to be represented in any type"));
3695 return irb->codegen->invalid_instruction;3708 return irb->codegen->invalid_instruction;
3696 }3709 }
36973710
3698 return ir_build_const_bignum(irb, scope, node, node->data.number_literal.bignum);3711 return ir_build_const_bigfloat(irb, scope, node, node->data.float_literal.bigfloat);
3699}3712}
37003713
3701static IrInstruction *ir_gen_char_lit(IrBuilder *irb, Scope *scope, AstNode *node) {3714static IrInstruction *ir_gen_char_lit(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -5933,8 +5946,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -5933,8 +5946,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
5933 return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval);5946 return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval);
5934 case NodeTypeBinOpExpr:5947 case NodeTypeBinOpExpr:
5935 return ir_lval_wrap(irb, scope, ir_gen_bin_op(irb, scope, node), lval);5948 return ir_lval_wrap(irb, scope, ir_gen_bin_op(irb, scope, node), lval);
5936 case NodeTypeNumberLiteral:5949 case NodeTypeIntLiteral:
5937 return ir_lval_wrap(irb, scope, ir_gen_num_lit(irb, scope, node), lval);5950 return ir_lval_wrap(irb, scope, ir_gen_int_lit(irb, scope, node), lval);
5951 case NodeTypeFloatLiteral:
5952 return ir_lval_wrap(irb, scope, ir_gen_float_lit(irb, scope, node), lval);
5938 case NodeTypeCharLiteral:5953 case NodeTypeCharLiteral:
5939 return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval);5954 return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval);
5940 case NodeTypeSymbol:5955 case NodeTypeSymbol:
...@@ -6184,6 +6199,13 @@ static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *so...@@ -6184,6 +6199,13 @@ static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *so
6184 return true;6199 return true;
6185}6200}
61866201
6202static bool const_val_fits_in_num_lit(ConstExprValue *const_val, TypeTableEntry *num_lit_type) {
6203 return ((num_lit_type->id == TypeTableEntryIdNumLitFloat &&
6204 (const_val->type->id == TypeTableEntryIdFloat || const_val->type->id == TypeTableEntryIdNumLitFloat)) ||
6205 (num_lit_type->id == TypeTableEntryIdNumLitInt &&
6206 (const_val->type->id == TypeTableEntryIdInt || const_val->type->id == TypeTableEntryIdNumLitInt)));
6207}
6208
6187static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) {6209static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) {
6188 if (type_is_invalid(other_type)) {6210 if (type_is_invalid(other_type)) {
6189 return false;6211 return false;
...@@ -6191,44 +6213,51 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -6191,44 +6213,51 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
61916213
6192 ConstExprValue *const_val = &instruction->value;6214 ConstExprValue *const_val = &instruction->value;
6193 assert(const_val->special != ConstValSpecialRuntime);6215 assert(const_val->special != ConstValSpecialRuntime);
6216
6217 bool const_val_is_int = (const_val->type->id == TypeTableEntryIdInt ||
6218 const_val->type->id == TypeTableEntryIdNumLitInt);
6219 bool const_val_is_float = (const_val->type->id == TypeTableEntryIdFloat ||
6220 const_val->type->id == TypeTableEntryIdNumLitFloat);
6194 if (other_type->id == TypeTableEntryIdFloat) {6221 if (other_type->id == TypeTableEntryIdFloat) {
6195 return true;6222 return true;
6196 } else if (other_type->id == TypeTableEntryIdInt &&6223 } else if (other_type->id == TypeTableEntryIdInt && const_val_is_int) {
6197 const_val->data.x_bignum.kind == BigNumKindInt)6224 if (bigint_fits_in_bits(&const_val->data.x_bigint, other_type->data.integral.bit_count,
6198 {
6199 if (bignum_fits_in_bits(&const_val->data.x_bignum, other_type->data.integral.bit_count,
6200 other_type->data.integral.is_signed))6225 other_type->data.integral.is_signed))
6201 {6226 {
6202 return true;6227 return true;
6203 }6228 }
6204 } else if ((other_type->id == TypeTableEntryIdNumLitFloat && const_val->data.x_bignum.kind == BigNumKindFloat) ||6229 } else if (const_val_fits_in_num_lit(const_val, other_type)) {
6205 (other_type->id == TypeTableEntryIdNumLitInt && const_val->data.x_bignum.kind == BigNumKindInt ))
6206 {
6207 return true;6230 return true;
6208 } else if (other_type->id == TypeTableEntryIdMaybe) {6231 } else if (other_type->id == TypeTableEntryIdMaybe) {
6209 TypeTableEntry *child_type = other_type->data.maybe.child_type;6232 TypeTableEntry *child_type = other_type->data.maybe.child_type;
6210 if ((child_type->id == TypeTableEntryIdNumLitFloat && const_val->data.x_bignum.kind == BigNumKindFloat) ||6233 if (const_val_fits_in_num_lit(const_val, child_type)) {
6211 (child_type->id == TypeTableEntryIdNumLitInt && const_val->data.x_bignum.kind == BigNumKindInt ))
6212 {
6213 return true;6234 return true;
6214 } else if (child_type->id == TypeTableEntryIdInt && const_val->data.x_bignum.kind == BigNumKindInt) {6235 } else if (child_type->id == TypeTableEntryIdInt && const_val_is_int) {
6215 if (bignum_fits_in_bits(&const_val->data.x_bignum,6236 if (bigint_fits_in_bits(&const_val->data.x_bigint,
6216 child_type->data.integral.bit_count,6237 child_type->data.integral.bit_count,
6217 child_type->data.integral.is_signed))6238 child_type->data.integral.is_signed))
6218 {6239 {
6219 return true;6240 return true;
6220 }6241 }
6221 } else if (child_type->id == TypeTableEntryIdFloat && const_val->data.x_bignum.kind == BigNumKindFloat) {6242 } else if (child_type->id == TypeTableEntryIdFloat && const_val_is_float) {
6222 return true;6243 return true;
6223 }6244 }
6224 }6245 }
62256246
6226 const char *num_lit_str = (const_val->data.x_bignum.kind == BigNumKindFloat) ? "float" : "integer";6247 const char *num_lit_str;
6248 Buf *val_buf = buf_alloc();
6249 if (const_val_is_float) {
6250 num_lit_str = "float";
6251 bigfloat_write_buf(val_buf, &const_val->data.x_bigfloat);
6252 } else {
6253 num_lit_str = "integer";
6254 bigint_write_buf(val_buf, &const_val->data.x_bigint, 10);
6255 }
62276256
6228 ir_add_error(ira, instruction,6257 ir_add_error(ira, instruction,
6229 buf_sprintf("%s value %s cannot be implicitly casted to type '%s'",6258 buf_sprintf("%s value %s cannot be implicitly casted to type '%s'",
6230 num_lit_str,6259 num_lit_str,
6231 buf_ptr(bignum_to_buf(&const_val->data.x_bignum)),6260 buf_ptr(val_buf),
6232 buf_ptr(&other_type->name)));6261 buf_ptr(&other_type->name)));
6233 return false;6262 return false;
6234}6263}
...@@ -6643,7 +6672,13 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -6643,7 +6672,13 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
6643 break;6672 break;
6644 }6673 }
6645 case CastOpNumLitToConcrete:6674 case CastOpNumLitToConcrete:
6646 const_val->data.x_bignum = other_val->data.x_bignum;6675 if (other_val->type->id == TypeTableEntryIdNumLitFloat) {
6676 bigfloat_init_bigfloat(&const_val->data.x_bigfloat, &other_val->data.x_bigfloat);
6677 } else if (other_val->type->id == TypeTableEntryIdNumLitInt) {
6678 bigint_init_bigint(&const_val->data.x_bigint, &other_val->data.x_bigint);
6679 } else {
6680 zig_unreachable();
6681 }
6647 const_val->type = new_type;6682 const_val->type = new_type;
6648 break;6683 break;
6649 case CastOpResizeSlice:6684 case CastOpResizeSlice:
...@@ -6651,15 +6686,15 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -6651,15 +6686,15 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
6651 // can't do it6686 // can't do it
6652 break;6687 break;
6653 case CastOpIntToFloat:6688 case CastOpIntToFloat:
6654 bignum_cast_to_float(&const_val->data.x_bignum, &other_val->data.x_bignum);6689 bigfloat_init_bigint(&const_val->data.x_bigfloat, &other_val->data.x_bigint);
6655 const_val->special = ConstValSpecialStatic;6690 const_val->special = ConstValSpecialStatic;
6656 break;6691 break;
6657 case CastOpFloatToInt:6692 case CastOpFloatToInt:
6658 bignum_cast_to_int(&const_val->data.x_bignum, &other_val->data.x_bignum);6693 bigint_init_bigfloat(&const_val->data.x_bigint, &other_val->data.x_bigfloat);
6659 const_val->special = ConstValSpecialStatic;6694 const_val->special = ConstValSpecialStatic;
6660 break;6695 break;
6661 case CastOpBoolToInt:6696 case CastOpBoolToInt:
6662 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_bool ? 1 : 0);6697 bigint_init_unsigned(&const_val->data.x_bigint, other_val->data.x_bool ? 1 : 0);
6663 const_val->special = ConstValSpecialStatic;6698 const_val->special = ConstValSpecialStatic;
6664 break;6699 break;
6665 }6700 }
...@@ -6878,7 +6913,7 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr...@@ -6878,7 +6913,7 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr
68786913
6879static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value) {6914static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value) {
6880 ConstExprValue *const_val = ir_build_const_from(ira, instruction);6915 ConstExprValue *const_val = ir_build_const_from(ira, instruction);
6881 bignum_init_unsigned(&const_val->data.x_bignum, value);6916 bigint_init_unsigned(&const_val->data.x_bigint, value);
6882 return ira->codegen->builtin_types.entry_usize;6917 return ira->codegen->builtin_types.entry_usize;
6883}6918}
68846919
...@@ -7239,12 +7274,12 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction...@@ -7239,12 +7274,12 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
7239 if (!val)7274 if (!val)
7240 return ira->codegen->invalid_instruction;7275 return ira->codegen->invalid_instruction;
7241 if (wanted_type->id == TypeTableEntryIdInt) {7276 if (wanted_type->id == TypeTableEntryIdInt) {
7242 if (val->data.x_bignum.is_negative && !wanted_type->data.integral.is_signed) {7277 if (bigint_cmp_zero(&val->data.x_bigint) == CmpLT && !wanted_type->data.integral.is_signed) {
7243 ir_add_error(ira, source_instr,7278 ir_add_error(ira, source_instr,
7244 buf_sprintf("attempt to cast negative value to unsigned integer"));7279 buf_sprintf("attempt to cast negative value to unsigned integer"));
7245 return ira->codegen->invalid_instruction;7280 return ira->codegen->invalid_instruction;
7246 }7281 }
7247 if (!bignum_fits_in_bits(&val->data.x_bignum, wanted_type->data.integral.bit_count,7282 if (!bigint_fits_in_bits(&val->data.x_bigint, wanted_type->data.integral.bit_count,
7248 wanted_type->data.integral.is_signed))7283 wanted_type->data.integral.is_signed))
7249 {7284 {
7250 ir_add_error(ira, source_instr,7285 ir_add_error(ira, source_instr,
...@@ -7255,7 +7290,11 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction...@@ -7255,7 +7290,11 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
7255 }7290 }
7256 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,7291 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
7257 source_instr->source_node, wanted_type);7292 source_instr->source_node, wanted_type);
7258 result->value.data.x_bignum = val->data.x_bignum;7293 if (wanted_type->id == TypeTableEntryIdInt) {
7294 bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint);
7295 } else {
7296 bigfloat_init_bigfloat(&result->value.data.x_bigfloat, &val->data.x_bigfloat);
7297 }
7259 result->value.type = wanted_type;7298 result->value.type = wanted_type;
7260 return result;7299 return result;
7261 }7300 }
...@@ -7278,7 +7317,7 @@ static IrInstruction *ir_analyze_ptr_to_int(IrAnalyze *ira, IrInstruction *sourc...@@ -7278,7 +7317,7 @@ static IrInstruction *ir_analyze_ptr_to_int(IrAnalyze *ira, IrInstruction *sourc
7278 if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {7317 if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
7279 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,7318 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
7280 source_instr->source_node, wanted_type);7319 source_instr->source_node, wanted_type);
7281 bignum_init_unsigned(&result->value.data.x_bignum, val->data.x_ptr.data.hard_coded_addr.addr);7320 bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
7282 return result;7321 return result;
7283 }7322 }
7284 }7323 }
...@@ -7299,9 +7338,20 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -7299,9 +7338,20 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
7299 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);7338 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
7300 if (!val)7339 if (!val)
7301 return ira->codegen->invalid_instruction;7340 return ira->codegen->invalid_instruction;
7341 BigInt enum_member_count;
7342 bigint_init_unsigned(&enum_member_count, wanted_type->data.enumeration.src_field_count);
7343 if (bigint_cmp(&val->data.x_bigint, &enum_member_count) != CmpLT) {
7344 Buf *val_buf = buf_alloc();
7345 bigint_write_buf(val_buf, &val->data.x_bigint, 10);
7346 ir_add_error(ira, source_instr,
7347 buf_sprintf("integer value %s too big for enum '%s' which has %" PRIu32 " fields",
7348 buf_ptr(val_buf), buf_ptr(&wanted_type->name), wanted_type->data.enumeration.src_field_count));
7349 return ira->codegen->invalid_instruction;
7350 }
7351
7302 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,7352 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
7303 source_instr->source_node, wanted_type);7353 source_instr->source_node, wanted_type);
7304 result->value.data.x_enum.tag = val->data.x_bignum.data.x_uint;7354 result->value.data.x_enum.tag = bigint_as_unsigned(&val->data.x_bigint);
7305 return result;7355 return result;
7306 }7356 }
73077357
...@@ -7320,7 +7370,13 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction...@@ -7320,7 +7370,13 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction
73207370
7321 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,7371 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
7322 source_instr->source_node, wanted_type);7372 source_instr->source_node, wanted_type);
7323 bignum_init_bignum(&result->value.data.x_bignum, &val->data.x_bignum);7373 if (wanted_type->id == TypeTableEntryIdNumLitFloat) {
7374 bigfloat_init_bigfloat(&result->value.data.x_bigfloat, &val->data.x_bigfloat);
7375 } else if (wanted_type->id == TypeTableEntryIdNumLitInt) {
7376 bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint);
7377 } else {
7378 zig_unreachable();
7379 }
7324 return result;7380 return result;
7325}7381}
73267382
...@@ -7336,13 +7392,17 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc...@@ -7336,13 +7392,17 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
7336 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,7392 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
7337 source_instr->source_node, ira->codegen->builtin_types.entry_pure_error);7393 source_instr->source_node, ira->codegen->builtin_types.entry_pure_error);
73387394
7339 uint64_t index = val->data.x_bignum.data.x_uint;7395 BigInt err_count;
7340 if (index == 0 || index >= ira->codegen->error_decls.length) {7396 bigint_init_unsigned(&err_count, ira->codegen->error_decls.length);
7397 if (bigint_cmp_zero(&val->data.x_bigint) == CmpEQ || bigint_cmp(&val->data.x_bigint, &err_count) != CmpLT) {
7398 Buf *val_buf = buf_alloc();
7399 bigint_write_buf(val_buf, &val->data.x_bigint, 10);
7341 ir_add_error(ira, source_instr,7400 ir_add_error(ira, source_instr,
7342 buf_sprintf("integer value %" ZIG_PRI_u64 " represents no error", index));7401 buf_sprintf("integer value %s represents no error", buf_ptr(val_buf)));
7343 return ira->codegen->invalid_instruction;7402 return ira->codegen->invalid_instruction;
7344 }7403 }
73457404
7405 size_t index = bigint_as_unsigned(&val->data.x_bigint);
7346 AstNode *error_decl_node = ira->codegen->error_decls.at(index);7406 AstNode *error_decl_node = ira->codegen->error_decls.at(index);
7347 result->value.data.x_pure_err = error_decl_node->data.error_value_decl.err;7407 result->value.data.x_pure_err = error_decl_node->data.error_value_decl.err;
7348 return result;7408 return result;
...@@ -7378,9 +7438,9 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc...@@ -7378,9 +7438,9 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
7378 }7438 }
7379 result->value.type = wanted_type;7439 result->value.type = wanted_type;
7380 uint64_t err_value = err ? err->value : 0;7440 uint64_t err_value = err ? err->value : 0;
7381 bignum_init_unsigned(&result->value.data.x_bignum, err_value);7441 bigint_init_unsigned(&result->value.data.x_bigint, err_value);
73827442
7383 if (!bignum_fits_in_bits(&result->value.data.x_bignum,7443 if (!bigint_fits_in_bits(&result->value.data.x_bigint,
7384 wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed))7444 wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed))
7385 {7445 {
7386 ir_add_error_node(ira, source_instr->source_node,7446 ir_add_error_node(ira, source_instr->source_node,
...@@ -7392,9 +7452,9 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc...@@ -7392,9 +7452,9 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
7392 return result;7452 return result;
7393 }7453 }
73947454
7395 BigNum bn;7455 BigInt bn;
7396 bignum_init_unsigned(&bn, ira->codegen->error_decls.length);7456 bigint_init_unsigned(&bn, ira->codegen->error_decls.length);
7397 if (!bignum_fits_in_bits(&bn, wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed)) {7457 if (!bigint_fits_in_bits(&bn, wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed)) {
7398 ir_add_error_node(ira, source_instr->source_node,7458 ir_add_error_node(ira, source_instr->source_node,
7399 buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name)));7459 buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name)));
7400 return ira->codegen->invalid_instruction;7460 return ira->codegen->invalid_instruction;
...@@ -7861,7 +7921,7 @@ static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out...@@ -7861,7 +7921,7 @@ static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out
7861 if (!const_val)7921 if (!const_val)
7862 return false;7922 return false;
78637923
7864 *out = const_val->data.x_bignum.data.x_uint;7924 *out = bigint_as_unsigned(&const_val->data.x_bigint);
7865 return true;7925 return true;
7866}7926}
78677927
...@@ -7941,7 +8001,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {...@@ -7941,7 +8001,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
7941 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);8001 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
7942 ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;8002 ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
7943 expand_undef_array(ira->codegen, array_val);8003 expand_undef_array(ira->codegen, array_val);
7944 size_t len = len_field->data.x_bignum.data.x_uint;8004 size_t len = bigint_as_unsigned(&len_field->data.x_bigint);
7945 Buf *result = buf_alloc();8005 Buf *result = buf_alloc();
7946 buf_resize(result, len);8006 buf_resize(result, len);
7947 for (size_t i = 0; i < len; i += 1) {8007 for (size_t i = 0; i < len; i += 1) {
...@@ -7951,7 +8011,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {...@@ -7951,7 +8011,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
7951 ir_add_error(ira, casted_value, buf_sprintf("use of undefined value"));8011 ir_add_error(ira, casted_value, buf_sprintf("use of undefined value"));
7952 return nullptr;8012 return nullptr;
7953 }8013 }
7954 uint64_t big_c = char_val->data.x_bignum.data.x_uint;8014 uint64_t big_c = bigint_as_unsigned(&char_val->data.x_bigint);
7955 assert(big_c <= UINT8_MAX);8015 assert(big_c <= UINT8_MAX);
7956 uint8_t c = (uint8_t)big_c;8016 uint8_t c = (uint8_t)big_c;
7957 buf_ptr(result)[i] = c;8017 buf_ptr(result)[i] = c;
...@@ -8039,6 +8099,24 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp...@@ -8039,6 +8099,24 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
8039 return bool_type;8099 return bool_type;
8040}8100}
80418101
8102static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
8103 if (op_id == IrBinOpCmpEq) {
8104 return cmp == CmpEQ;
8105 } else if (op_id == IrBinOpCmpNotEq) {
8106 return cmp != CmpEQ;
8107 } else if (op_id == IrBinOpCmpLessThan) {
8108 return cmp == CmpLT;
8109 } else if (op_id == IrBinOpCmpGreaterThan) {
8110 return cmp == CmpGT;
8111 } else if (op_id == IrBinOpCmpLessOrEq) {
8112 return cmp != CmpGT;
8113 } else if (op_id == IrBinOpCmpGreaterOrEq) {
8114 return cmp != CmpLT;
8115 } else {
8116 zig_unreachable();
8117 }
8118}
8119
8042static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {8120static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
8043 IrInstruction *op1 = bin_op_instruction->op1->other;8121 IrInstruction *op1 = bin_op_instruction->op1->other;
8044 IrInstruction *op2 = bin_op_instruction->op2->other;8122 IrInstruction *op2 = bin_op_instruction->op2->other;
...@@ -8157,30 +8235,13 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -8157,30 +8235,13 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
8157 ConstExprValue *op1_val = &casted_op1->value;8235 ConstExprValue *op1_val = &casted_op1->value;
8158 ConstExprValue *op2_val = &casted_op2->value;8236 ConstExprValue *op2_val = &casted_op2->value;
8159 if ((value_is_comptime(op1_val) && value_is_comptime(op2_val)) || resolved_type->id == TypeTableEntryIdVoid) {8237 if ((value_is_comptime(op1_val) && value_is_comptime(op2_val)) || resolved_type->id == TypeTableEntryIdVoid) {
8160 bool type_can_gt_lt_cmp = (resolved_type->id == TypeTableEntryIdNumLitFloat ||
8161 resolved_type->id == TypeTableEntryIdNumLitInt ||
8162 resolved_type->id == TypeTableEntryIdFloat ||
8163 resolved_type->id == TypeTableEntryIdInt);
8164 bool answer;8238 bool answer;
8165 if (type_can_gt_lt_cmp) {8239 if (resolved_type->id == TypeTableEntryIdNumLitFloat || resolved_type->id == TypeTableEntryIdFloat) {
8166 bool (*bignum_cmp)(BigNum *, BigNum *);8240 Cmp cmp_result = bigfloat_cmp(&op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8167 if (op_id == IrBinOpCmpEq) {8241 answer = resolve_cmp_op_id(op_id, cmp_result);
8168 bignum_cmp = bignum_cmp_eq;8242 } else if (resolved_type->id == TypeTableEntryIdNumLitInt || resolved_type->id == TypeTableEntryIdInt) {
8169 } else if (op_id == IrBinOpCmpNotEq) {8243 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
8170 bignum_cmp = bignum_cmp_neq;8244 answer = resolve_cmp_op_id(op_id, cmp_result);
8171 } else if (op_id == IrBinOpCmpLessThan) {
8172 bignum_cmp = bignum_cmp_lt;
8173 } else if (op_id == IrBinOpCmpGreaterThan) {
8174 bignum_cmp = bignum_cmp_gt;
8175 } else if (op_id == IrBinOpCmpLessOrEq) {
8176 bignum_cmp = bignum_cmp_lte;
8177 } else if (op_id == IrBinOpCmpGreaterOrEq) {
8178 bignum_cmp = bignum_cmp_gte;
8179 } else {
8180 zig_unreachable();
8181 }
8182
8183 answer = bignum_cmp(&op1_val->data.x_bignum, &op2_val->data.x_bignum);
8184 } else {8245 } else {
8185 bool are_equal = resolved_type->id == TypeTableEntryIdVoid || const_values_equal(op1_val, op2_val);8246 bool are_equal = resolved_type->id == TypeTableEntryIdVoid || const_values_equal(op1_val, op2_val);
8186 if (op_id == IrBinOpCmpEq) {8247 if (op_id == IrBinOpCmpEq) {
...@@ -8220,7 +8281,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -8220,7 +8281,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
8220 } else {8281 } else {
8221 known_left_val = nullptr;8282 known_left_val = nullptr;
8222 }8283 }
8223 if (known_left_val != nullptr && known_left_val->data.x_bignum.data.x_uint == 0 &&8284 if (known_left_val != nullptr && bigint_cmp_zero(&known_left_val->data.x_bigint) == CmpEQ &&
8224 (flipped_op_id == IrBinOpCmpLessOrEq || flipped_op_id == IrBinOpCmpGreaterThan))8285 (flipped_op_id == IrBinOpCmpLessOrEq || flipped_op_id == IrBinOpCmpGreaterThan))
8225 {8286 {
8226 bool answer = (flipped_op_id == IrBinOpCmpLessOrEq);8287 bool answer = (flipped_op_id == IrBinOpCmpLessOrEq);
...@@ -8236,101 +8297,35 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -8236,101 +8297,35 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
8236 return ira->codegen->builtin_types.entry_bool;8297 return ira->codegen->builtin_types.entry_bool;
8237}8298}
82388299
8239enum EvalBigNumSpecial {8300static int ir_eval_math_op(TypeTableEntry *type_entry, ConstExprValue *op1_val,
8240 EvalBigNumSpecialNone,8301 IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
8241 EvalBigNumSpecialWrapping,
8242 EvalBigNumSpecialExact,
8243};
8244
8245static int ir_eval_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,
8246 ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *),
8247 TypeTableEntry *type, EvalBigNumSpecial special)
8248{8302{
8249 bool is_int = false;8303 bool is_int;
8250 bool is_float = false;8304 bool is_float;
8251 if (type->id == TypeTableEntryIdInt ||8305 Cmp op2_zcmp;
8252 type->id == TypeTableEntryIdNumLitInt)8306 if (type_entry->id == TypeTableEntryIdInt || type_entry->id == TypeTableEntryIdNumLitInt) {
8253 {
8254 is_int = true;8307 is_int = true;
8255 } else if (type->id == TypeTableEntryIdFloat ||8308 is_float = false;
8256 type->id == TypeTableEntryIdNumLitFloat)8309 op2_zcmp = bigint_cmp_zero(&op2_val->data.x_bigint);
8310 } else if (type_entry->id == TypeTableEntryIdFloat ||
8311 type_entry->id == TypeTableEntryIdNumLitFloat)
8257 {8312 {
8313 is_int = false;
8258 is_float = true;8314 is_float = true;
8315 op2_zcmp = bigfloat_cmp_zero(&op2_val->data.x_bigfloat);
8259 } else {8316 } else {
8260 zig_unreachable();8317 zig_unreachable();
8261 }8318 }
8262 if (bignum_fn == bignum_div || bignum_fn == bignum_rem || bignum_fn == bignum_mod ||
8263 bignum_fn == bignum_div_trunc || bignum_fn == bignum_div_floor)
8264 {
8265 if ((is_int && op2_val->data.x_bignum.data.x_uint == 0) ||
8266 (is_float && op2_val->data.x_bignum.data.x_float == 0.0))
8267 {
8268 return ErrorDivByZero;
8269 }
8270 }
8271 if (bignum_fn == bignum_rem || bignum_fn == bignum_mod) {
8272 BigNum zero;
8273 if (is_float) {
8274 bignum_init_float(&zero, 0.0);
8275 } else {
8276 bignum_init_unsigned(&zero, 0);
8277 }
8278 if (bignum_cmp_lt(&op2_val->data.x_bignum, &zero)) {
8279 return ErrorNegativeDenominator;
8280 }
8281 }
8282
8283 if (special == EvalBigNumSpecialExact) {
8284 assert(bignum_fn == bignum_div);
8285 BigNum remainder;
8286 if (bignum_rem(&remainder, &op1_val->data.x_bignum, &op2_val->data.x_bignum)) {
8287 return ErrorOverflow;
8288 }
8289 BigNum zero;
8290 if (is_float) {
8291 bignum_init_float(&zero, 0.0);
8292 } else {
8293 bignum_init_unsigned(&zero, 0);
8294 }
8295 if (bignum_cmp_neq(&remainder, &zero)) {
8296 return ErrorExactDivRemainder;
8297 }
8298 }
8299
8300 bool overflow = bignum_fn(&out_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum);
8301 if (overflow) {
8302 if (special == EvalBigNumSpecialWrapping) {
8303 zig_panic("TODO compiler bug, implement compile-time wrapping arithmetic for >= 64 bit ints");
8304 } else {
8305 return ErrorOverflow;
8306 }
8307 }
83088319
8309 if (type->id == TypeTableEntryIdInt && !bignum_fits_in_bits(&out_val->data.x_bignum,8320 if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod ||
8310 type->data.integral.bit_count, type->data.integral.is_signed))8321 op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ)
8311 {8322 {
8312 if (special == EvalBigNumSpecialWrapping) {8323 return ErrorDivByZero;
8313 if (type->data.integral.is_signed) {8324 }
8314 out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1;8325 if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) {
8315 out_val->data.x_bignum.is_negative = !out_val->data.x_bignum.is_negative;8326 return ErrorNegativeDenominator;
8316 } else if (out_val->data.x_bignum.is_negative) {
8317 out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1;
8318 out_val->data.x_bignum.is_negative = false;
8319 } else {
8320 bignum_truncate(&out_val->data.x_bignum, type->data.integral.bit_count);
8321 }
8322 } else {
8323 return ErrorOverflow;
8324 }
8325 }8327 }
83268328
8327 out_val->special = ConstValSpecialStatic;
8328 return 0;
8329}
8330
8331static int ir_eval_math_op(TypeTableEntry *canon_type, ConstExprValue *op1_val,
8332 IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
8333{
8334 switch (op_id) {8329 switch (op_id) {
8335 case IrBinOpInvalid:8330 case IrBinOpInvalid:
8336 case IrBinOpBoolOr:8331 case IrBinOpBoolOr:
...@@ -8346,43 +8341,128 @@ static int ir_eval_math_op(TypeTableEntry *canon_type, ConstExprValue *op1_val,...@@ -8346,43 +8341,128 @@ static int ir_eval_math_op(TypeTableEntry *canon_type, ConstExprValue *op1_val,
8346 case IrBinOpRemUnspecified:8341 case IrBinOpRemUnspecified:
8347 zig_unreachable();8342 zig_unreachable();
8348 case IrBinOpBinOr:8343 case IrBinOpBinOr:
8349 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_or, canon_type, EvalBigNumSpecialNone);8344 assert(is_int);
8345 bigint_or(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8346 break;
8350 case IrBinOpBinXor:8347 case IrBinOpBinXor:
8351 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_xor, canon_type, EvalBigNumSpecialNone);8348 assert(is_int);
8349 bigint_xor(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8350 break;
8352 case IrBinOpBinAnd:8351 case IrBinOpBinAnd:
8353 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_and, canon_type, EvalBigNumSpecialNone);8352 assert(is_int);
8353 bigint_and(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8354 break;
8354 case IrBinOpBitShiftLeft:8355 case IrBinOpBitShiftLeft:
8355 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, canon_type, EvalBigNumSpecialNone);8356 assert(is_int);
8357 bigint_shl(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8358 break;
8356 case IrBinOpBitShiftLeftWrap:8359 case IrBinOpBitShiftLeftWrap:
8357 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, canon_type, EvalBigNumSpecialWrapping);8360 assert(type_entry->id == TypeTableEntryIdInt);
8361 bigint_shl_wrap(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint,
8362 type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
8363 break;
8358 case IrBinOpBitShiftRight:8364 case IrBinOpBitShiftRight:
8359 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shr, canon_type, EvalBigNumSpecialNone);8365 assert(is_int);
8366 bigint_shr(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8367 break;
8360 case IrBinOpAdd:8368 case IrBinOpAdd:
8361 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, canon_type, EvalBigNumSpecialNone);8369 if (is_int) {
8370 bigint_add(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8371 } else {
8372 bigfloat_add(&out_val->data.x_bigfloat, &op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8373 }
8374 break;
8362 case IrBinOpAddWrap:8375 case IrBinOpAddWrap:
8363 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, canon_type, EvalBigNumSpecialWrapping);8376 assert(type_entry->id == TypeTableEntryIdInt);
8377 bigint_add_wrap(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint,
8378 type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
8379 break;
8364 case IrBinOpSub:8380 case IrBinOpSub:
8365 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, canon_type, EvalBigNumSpecialNone);8381 if (is_int) {
8382 bigint_sub(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8383 } else {
8384 bigfloat_sub(&out_val->data.x_bigfloat, &op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8385 }
8386 break;
8366 case IrBinOpSubWrap:8387 case IrBinOpSubWrap:
8367 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, canon_type, EvalBigNumSpecialWrapping);8388 assert(type_entry->id == TypeTableEntryIdInt);
8389 bigint_sub_wrap(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint,
8390 type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
8391 break;
8368 case IrBinOpMult:8392 case IrBinOpMult:
8369 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, canon_type, EvalBigNumSpecialNone);8393 if (is_int) {
8394 bigint_mul(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8395 } else {
8396 bigfloat_mul(&out_val->data.x_bigfloat, &op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8397 }
8398 break;
8370 case IrBinOpMultWrap:8399 case IrBinOpMultWrap:
8371 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, canon_type, EvalBigNumSpecialWrapping);8400 assert(type_entry->id == TypeTableEntryIdInt);
8401 bigint_mul_wrap(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint,
8402 type_entry->data.integral.bit_count, type_entry->data.integral.is_signed);
8403 break;
8372 case IrBinOpDivUnspecified:8404 case IrBinOpDivUnspecified:
8373 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_div, canon_type, EvalBigNumSpecialNone);8405 assert(is_float);
8406 bigfloat_div(&out_val->data.x_bigfloat, &op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8407 break;
8374 case IrBinOpDivTrunc:8408 case IrBinOpDivTrunc:
8375 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_div_trunc, canon_type, EvalBigNumSpecialNone);8409 if (is_int) {
8410 bigint_div_trunc(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8411 } else {
8412 bigfloat_div_trunc(&out_val->data.x_bigfloat, &op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8413 }
8414 break;
8376 case IrBinOpDivFloor:8415 case IrBinOpDivFloor:
8377 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_div_floor, canon_type, EvalBigNumSpecialNone);8416 if (is_int) {
8417 bigint_div_floor(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8418 } else {
8419 bigfloat_div_floor(&out_val->data.x_bigfloat, &op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8420 }
8421 break;
8378 case IrBinOpDivExact:8422 case IrBinOpDivExact:
8379 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_div, canon_type, EvalBigNumSpecialExact);8423 if (is_int) {
8424 bigint_div_trunc(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8425 BigInt remainder;
8426 bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8427 if (bigint_cmp_zero(&remainder) != CmpEQ) {
8428 return ErrorExactDivRemainder;
8429 }
8430 } else {
8431 bigfloat_div_trunc(&out_val->data.x_bigfloat, &op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8432 BigFloat remainder;
8433 bigfloat_rem(&remainder, &op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8434 if (bigfloat_cmp_zero(&remainder) != CmpEQ) {
8435 return ErrorExactDivRemainder;
8436 }
8437 }
8438 break;
8380 case IrBinOpRemRem:8439 case IrBinOpRemRem:
8381 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_rem, canon_type, EvalBigNumSpecialNone);8440 if (is_int) {
8441 bigint_rem(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8442 } else {
8443 bigfloat_rem(&out_val->data.x_bigfloat, &op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8444 }
8445 break;
8382 case IrBinOpRemMod:8446 case IrBinOpRemMod:
8383 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mod, canon_type, EvalBigNumSpecialNone);8447 if (is_int) {
8448 bigint_mod(&out_val->data.x_bigint, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
8449 } else {
8450 bigfloat_mod(&out_val->data.x_bigfloat, &op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8451 }
8452 break;
8384 }8453 }
8385 zig_unreachable();8454
8455 if (type_entry->id == TypeTableEntryIdInt) {
8456 if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count,
8457 type_entry->data.integral.is_signed))
8458 {
8459 return ErrorOverflow;
8460 }
8461 }
8462
8463 out_val->type = type_entry;
8464 out_val->special = ConstValSpecialStatic;
8465 return 0;
8386}8466}
83878467
8388static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {8468static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
...@@ -8395,31 +8475,32 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -8395,31 +8475,32 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
8395 IrBinOp op_id = bin_op_instruction->op_id;8475 IrBinOp op_id = bin_op_instruction->op_id;
83968476
8397 bool is_int = resolved_type->id == TypeTableEntryIdInt || resolved_type->id == TypeTableEntryIdNumLitInt;8477 bool is_int = resolved_type->id == TypeTableEntryIdInt || resolved_type->id == TypeTableEntryIdNumLitInt;
8398 bool is_signed = ((resolved_type->id == TypeTableEntryIdInt && resolved_type->data.integral.is_signed) ||8478 bool is_float = resolved_type->id == TypeTableEntryIdFloat || resolved_type->id == TypeTableEntryIdNumLitFloat;
8399 resolved_type->id == TypeTableEntryIdFloat ||8479 bool is_signed_div = (
8400 (resolved_type->id == TypeTableEntryIdNumLitFloat &&8480 (resolved_type->id == TypeTableEntryIdInt && resolved_type->data.integral.is_signed) ||
8401 (op1->value.data.x_bignum.data.x_float < 0.0 || op2->value.data.x_bignum.data.x_float < 0.0)) ||8481 resolved_type->id == TypeTableEntryIdFloat ||
8402 (resolved_type->id == TypeTableEntryIdNumLitInt &&8482 (resolved_type->id == TypeTableEntryIdNumLitFloat &&
8403 (op1->value.data.x_bignum.is_negative || op2->value.data.x_bignum.is_negative)));8483 ((bigfloat_cmp_zero(&op1->value.data.x_bigfloat) != CmpGT) !=
8404 if (op_id == IrBinOpDivUnspecified) {8484 (bigfloat_cmp_zero(&op2->value.data.x_bigfloat) != CmpGT))) ||
8405 if (is_int && is_signed) {8485 (resolved_type->id == TypeTableEntryIdNumLitInt &&
8486 ((bigint_cmp_zero(&op1->value.data.x_bigint) != CmpGT) !=
8487 (bigint_cmp_zero(&op2->value.data.x_bigint) != CmpGT)))
8488 );
8489 if (op_id == IrBinOpDivUnspecified && is_int) {
8490 if (is_signed_div) {
8406 bool ok = false;8491 bool ok = false;
8407 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {8492 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
8408 if (op2->value.data.x_bignum.data.x_uint == 0) {8493 if (bigint_cmp_zero(&op2->value.data.x_bigint) == CmpEQ) {
8409 // the division by zero error will be caught later, but we don't have a8494 // the division by zero error will be caught later, but we don't have a
8410 // division function ambiguity problem.8495 // division function ambiguity problem.
8411 op_id = IrBinOpDivTrunc;8496 op_id = IrBinOpDivTrunc;
8412 ok = true;8497 ok = true;
8413 } else {8498 } else {
8414 BigNum trunc_result;8499 BigInt trunc_result;
8415 BigNum floor_result;8500 BigInt floor_result;
8416 if (bignum_div_trunc(&trunc_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {8501 bigint_div_trunc(&trunc_result, &op1->value.data.x_bigint, &op2->value.data.x_bigint);
8417 zig_unreachable();8502 bigint_div_floor(&floor_result, &op1->value.data.x_bigint, &op2->value.data.x_bigint);
8418 }8503 if (bigint_cmp(&trunc_result, &floor_result) == CmpEQ) {
8419 if (bignum_div_floor(&floor_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8420 zig_unreachable();
8421 }
8422 if (bignum_cmp_eq(&trunc_result, &floor_result)) {
8423 ok = true;8504 ok = true;
8424 op_id = IrBinOpDivTrunc;8505 op_id = IrBinOpDivTrunc;
8425 }8506 }
...@@ -8432,29 +8513,37 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -8432,29 +8513,37 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
8432 buf_ptr(&op2->value.type->name)));8513 buf_ptr(&op2->value.type->name)));
8433 return ira->codegen->builtin_types.entry_invalid;8514 return ira->codegen->builtin_types.entry_invalid;
8434 }8515 }
8435 } else if (is_int) {8516 } else {
8436 op_id = IrBinOpDivTrunc;8517 op_id = IrBinOpDivTrunc;
8437 }8518 }
8438 } else if (op_id == IrBinOpRemUnspecified) {8519 } else if (op_id == IrBinOpRemUnspecified) {
8439 if (is_signed) {8520 if (is_signed_div && (is_int || is_float)) {
8440 bool ok = false;8521 bool ok = false;
8441 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {8522 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
8442 if ((is_int && op2->value.data.x_bignum.data.x_uint == 0) ||8523 if (is_int) {
8443 (!is_int && op2->value.data.x_bignum.data.x_float == 0.0))8524 if (bigint_cmp_zero(&op2->value.data.x_bigint) == CmpEQ) {
8444 {8525 // the division by zero error will be caught later, but we don't
8445 // the division by zero error will be caught later, but we don't8526 // have a remainder function ambiguity problem
8446 // have a remainder function ambiguity problem8527 ok = true;
8447 ok = true;8528 } else {
8448 } else {8529 BigInt rem_result;
8449 BigNum rem_result;8530 BigInt mod_result;
8450 BigNum mod_result;8531 bigint_rem(&rem_result, &op1->value.data.x_bigint, &op2->value.data.x_bigint);
8451 if (bignum_rem(&rem_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {8532 bigint_mod(&mod_result, &op1->value.data.x_bigint, &op2->value.data.x_bigint);
8452 zig_unreachable();8533 ok = bigint_cmp(&rem_result, &mod_result) == CmpEQ;
8453 }8534 }
8454 if (bignum_mod(&mod_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {8535 } else {
8455 zig_unreachable();8536 if (bigfloat_cmp_zero(&op2->value.data.x_bigfloat) == CmpEQ) {
8537 // the division by zero error will be caught later, but we don't
8538 // have a remainder function ambiguity problem
8539 ok = true;
8540 } else {
8541 BigFloat rem_result;
8542 BigFloat mod_result;
8543 bigfloat_rem(&rem_result, &op1->value.data.x_bigfloat, &op2->value.data.x_bigfloat);
8544 bigfloat_mod(&mod_result, &op1->value.data.x_bigfloat, &op2->value.data.x_bigfloat);
8545 ok = bigfloat_cmp(&rem_result, &mod_result) == CmpEQ;
8456 }8546 }
8457 ok = bignum_cmp_eq(&rem_result, &mod_result);
8458 }8547 }
8459 }8548 }
8460 if (!ok) {8549 if (!ok) {
...@@ -8468,21 +8557,18 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -8468,21 +8557,18 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
8468 op_id = IrBinOpRemRem;8557 op_id = IrBinOpRemRem;
8469 }8558 }
84708559
8471 if (resolved_type->id == TypeTableEntryIdInt ||8560 if (is_int) {
8472 resolved_type->id == TypeTableEntryIdNumLitInt)
8473 {
8474 // int8561 // int
8475 } else if ((resolved_type->id == TypeTableEntryIdFloat ||8562 } else if (is_float &&
8476 resolved_type->id == TypeTableEntryIdNumLitFloat) &&
8477 (op_id == IrBinOpAdd ||8563 (op_id == IrBinOpAdd ||
8478 op_id == IrBinOpSub ||8564 op_id == IrBinOpSub ||
8479 op_id == IrBinOpMult ||8565 op_id == IrBinOpMult ||
8480 op_id == IrBinOpDivUnspecified ||8566 op_id == IrBinOpDivUnspecified ||
8481 op_id == IrBinOpDivTrunc ||8567 op_id == IrBinOpDivTrunc ||
8482 op_id == IrBinOpDivFloor ||8568 op_id == IrBinOpDivFloor ||
8483 op_id == IrBinOpDivExact ||8569 op_id == IrBinOpDivExact ||
8484 op_id == IrBinOpRemRem ||8570 op_id == IrBinOpRemRem ||
8485 op_id == IrBinOpRemMod))8571 op_id == IrBinOpRemMod))
8486 {8572 {
8487 // float8573 // float
8488 } else {8574 } else {
...@@ -8494,6 +8580,18 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -8494,6 +8580,18 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
8494 return ira->codegen->builtin_types.entry_invalid;8580 return ira->codegen->builtin_types.entry_invalid;
8495 }8581 }
84968582
8583 if (resolved_type->id == TypeTableEntryIdNumLitInt) {
8584 if (op_id == IrBinOpBitShiftLeftWrap) {
8585 op_id = IrBinOpBitShiftLeft;
8586 } else if (op_id == IrBinOpAddWrap) {
8587 op_id = IrBinOpAdd;
8588 } else if (op_id == IrBinOpSubWrap) {
8589 op_id = IrBinOpSub;
8590 } else if (op_id == IrBinOpMultWrap) {
8591 op_id = IrBinOpMult;
8592 }
8593 }
8594
8497 IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, resolved_type);8595 IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, resolved_type);
8498 if (casted_op1 == ira->codegen->invalid_instruction)8596 if (casted_op1 == ira->codegen->invalid_instruction)
8499 return ira->codegen->builtin_types.entry_invalid;8597 return ira->codegen->builtin_types.entry_invalid;
...@@ -8502,8 +8600,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -8502,8 +8600,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
8502 if (casted_op2 == ira->codegen->invalid_instruction)8600 if (casted_op2 == ira->codegen->invalid_instruction)
8503 return ira->codegen->builtin_types.entry_invalid;8601 return ira->codegen->builtin_types.entry_invalid;
85048602
85058603 if (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2)) {
8506 if (casted_op1->value.special != ConstValSpecialRuntime && casted_op2->value.special != ConstValSpecialRuntime) {
8507 ConstExprValue *op1_val = &casted_op1->value;8604 ConstExprValue *op1_val = &casted_op1->value;
8508 ConstExprValue *op2_val = &casted_op2->value;8605 ConstExprValue *op2_val = &casted_op2->value;
8509 ConstExprValue *out_val = &bin_op_instruction->base.value;8606 ConstExprValue *out_val = &bin_op_instruction->base.value;
...@@ -8704,17 +8801,17 @@ static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp...@@ -8704,17 +8801,17 @@ static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp
8704 }8801 }
87058802
8706 uint64_t old_array_len = array_type->data.array.len;8803 uint64_t old_array_len = array_type->data.array.len;
8804 uint64_t new_array_len;
87078805
8708 BigNum array_len;8806 if (__builtin_umulll_overflow((unsigned long long)old_array_len, (unsigned long long)mult_amt,
8709 bignum_init_unsigned(&array_len, old_array_len);8807 (unsigned long long*)&new_array_len))
8710 if (bignum_multiply_by_scalar(&array_len, mult_amt)) {8808 {
8711 ir_add_error(ira, &instruction->base, buf_sprintf("operation results in overflow"));8809 ir_add_error(ira, &instruction->base, buf_sprintf("operation results in overflow"));
8712 return ira->codegen->builtin_types.entry_invalid;8810 return ira->codegen->builtin_types.entry_invalid;
8713 }8811 }
87148812
8715 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);8813 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
87168814
8717 uint64_t new_array_len = array_len.data.x_uint;
8718 out_val->data.x_array.s_none.elements = create_const_vals(new_array_len);8815 out_val->data.x_array.s_none.elements = create_const_vals(new_array_len);
87198816
8720 expand_undef_array(ira->codegen, array_val);8817 expand_undef_array(ira->codegen, array_val);
...@@ -9581,9 +9678,10 @@ static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un...@@ -9581,9 +9678,10 @@ static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un
95819678
9582 bool is_wrap_op = (un_op_instruction->op_id == IrUnOpNegationWrap);9679 bool is_wrap_op = (un_op_instruction->op_id == IrUnOpNegationWrap);
95839680
9681 bool is_float = (expr_type->id == TypeTableEntryIdFloat || expr_type->id == TypeTableEntryIdNumLitFloat);
9682
9584 if ((expr_type->id == TypeTableEntryIdInt && expr_type->data.integral.is_signed) ||9683 if ((expr_type->id == TypeTableEntryIdInt && expr_type->data.integral.is_signed) ||
9585 expr_type->id == TypeTableEntryIdNumLitInt ||9684 expr_type->id == TypeTableEntryIdNumLitInt || (is_float && !is_wrap_op))
9586 ((expr_type->id == TypeTableEntryIdFloat || expr_type->id == TypeTableEntryIdNumLitFloat) && !is_wrap_op))
9587 {9685 {
9588 if (instr_is_comptime(value)) {9686 if (instr_is_comptime(value)) {
9589 ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);9687 ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
...@@ -9591,19 +9689,19 @@ static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un...@@ -9591,19 +9689,19 @@ static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un
9591 return ira->codegen->builtin_types.entry_invalid;9689 return ira->codegen->builtin_types.entry_invalid;
95929690
9593 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);9691 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
9594 bignum_negate(&out_val->data.x_bignum, &target_const_val->data.x_bignum);9692 if (is_float) {
9595 if (expr_type->id == TypeTableEntryIdFloat ||9693 bigfloat_negate(&out_val->data.x_bigfloat, &target_const_val->data.x_bigfloat);
9596 expr_type->id == TypeTableEntryIdNumLitFloat ||9694 } else if (is_wrap_op) {
9597 expr_type->id == TypeTableEntryIdNumLitInt)9695 bigint_negate_wrap(&out_val->data.x_bigint, &target_const_val->data.x_bigint,
9598 {9696 expr_type->data.integral.bit_count);
9697 } else {
9698 bigint_negate(&out_val->data.x_bigint, &target_const_val->data.x_bigint);
9699 }
9700 if (is_wrap_op || is_float || expr_type->id == TypeTableEntryIdNumLitInt) {
9599 return expr_type;9701 return expr_type;
9600 }9702 }
96019703
9602 bool overflow = !bignum_fits_in_bits(&out_val->data.x_bignum, expr_type->data.integral.bit_count, true);9704 if (!bigint_fits_in_bits(&out_val->data.x_bigint, expr_type->data.integral.bit_count, true)) {
9603 if (is_wrap_op) {
9604 if (overflow)
9605 out_val->data.x_bignum.is_negative = true;
9606 } else if (overflow) {
9607 ir_add_error(ira, &un_op_instruction->base, buf_sprintf("negation caused overflow"));9705 ir_add_error(ira, &un_op_instruction->base, buf_sprintf("negation caused overflow"));
9608 return ira->codegen->builtin_types.entry_invalid;9706 return ira->codegen->builtin_types.entry_invalid;
9609 }9707 }
...@@ -9632,7 +9730,7 @@ static TypeTableEntry *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *ins...@@ -9632,7 +9730,7 @@ static TypeTableEntry *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *ins
9632 return ira->codegen->builtin_types.entry_invalid;9730 return ira->codegen->builtin_types.entry_invalid;
96339731
9634 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);9732 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
9635 bignum_not(&out_val->data.x_bignum, &target_const_val->data.x_bignum,9733 bigint_not(&out_val->data.x_bigint, &target_const_val->data.x_bigint,
9636 expr_type->data.integral.bit_count, expr_type->data.integral.is_signed);9734 expr_type->data.integral.bit_count, expr_type->data.integral.is_signed);
9637 return expr_type;9735 return expr_type;
9638 }9736 }
...@@ -9887,12 +9985,12 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -9887,12 +9985,12 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
9887 return_type = get_pointer_to_type_extra(ira->codegen, child_type,9985 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
9888 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0);9986 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0);
9889 } else {9987 } else {
9890 ConstExprValue *elem_val = ir_resolve_const(ira, elem_index, UndefBad);9988 uint64_t elem_val_scalar;
9891 if (!elem_val)9989 if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))
9892 return ira->codegen->builtin_types.entry_invalid;9990 return ira->codegen->builtin_types.entry_invalid;
98939991
9894 size_t bit_width = type_size_bits(ira->codegen, child_type);9992 size_t bit_width = type_size_bits(ira->codegen, child_type);
9895 size_t bit_offset = bit_width * elem_val->data.x_bignum.data.x_uint;9993 size_t bit_offset = bit_width * elem_val_scalar;
98969994
9897 return_type = get_pointer_to_type_extra(ira->codegen, child_type,9995 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
9898 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,9996 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
...@@ -9909,10 +10007,10 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -9909,10 +10007,10 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
9909 ConstExprValue *args_val = const_ptr_pointee(ira->codegen, ptr_val);10007 ConstExprValue *args_val = const_ptr_pointee(ira->codegen, ptr_val);
9910 size_t start = args_val->data.x_arg_tuple.start_index;10008 size_t start = args_val->data.x_arg_tuple.start_index;
9911 size_t end = args_val->data.x_arg_tuple.end_index;10009 size_t end = args_val->data.x_arg_tuple.end_index;
9912 ConstExprValue *elem_index_val = ir_resolve_const(ira, elem_index, UndefBad);10010 uint64_t elem_index_val;
9913 if (!elem_index_val)10011 if (!ir_resolve_usize(ira, elem_index, &elem_index_val))
9914 return ira->codegen->builtin_types.entry_invalid;10012 return ira->codegen->builtin_types.entry_invalid;
9915 size_t index = bignum_to_twos_complement(&elem_index_val->data.x_bignum);10013 size_t index = elem_index_val;
9916 size_t len = end - start;10014 size_t len = end - start;
9917 if (index >= len) {10015 if (index >= len) {
9918 ir_add_error(ira, &elem_ptr_instruction->base,10016 ir_add_error(ira, &elem_ptr_instruction->base,
...@@ -9945,7 +10043,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -9945,7 +10043,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
994510043
9946 bool safety_check_on = elem_ptr_instruction->safety_check_on;10044 bool safety_check_on = elem_ptr_instruction->safety_check_on;
9947 if (instr_is_comptime(casted_elem_index)) {10045 if (instr_is_comptime(casted_elem_index)) {
9948 uint64_t index = casted_elem_index->value.data.x_bignum.data.x_uint;10046 uint64_t index = bigint_as_unsigned(&casted_elem_index->value.data.x_bigint);
9949 if (array_type->id == TypeTableEntryIdArray) {10047 if (array_type->id == TypeTableEntryIdArray) {
9950 uint64_t array_len = array_type->data.array.len;10048 uint64_t array_len = array_type->data.array.len;
9951 if (index >= array_len) {10049 if (index >= array_len) {
...@@ -10021,7 +10119,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -10021,7 +10119,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
10021 }10119 }
10022 ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];10120 ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];
10023 ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);10121 ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
10024 uint64_t slice_len = len_field->data.x_bignum.data.x_uint;10122 uint64_t slice_len = bigint_as_unsigned(&len_field->data.x_bigint);
10025 if (index >= slice_len) {10123 if (index >= slice_len) {
10026 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,10124 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
10027 buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,10125 buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,
...@@ -11107,7 +11205,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,...@@ -11107,7 +11205,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
11107 {11205 {
11108 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);11206 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
11109 ConstExprValue *out_val = ir_build_const_from(ira, &size_of_instruction->base);11207 ConstExprValue *out_val = ir_build_const_from(ira, &size_of_instruction->base);
11110 bignum_init_unsigned(&out_val->data.x_bignum, size_in_bytes);11208 bigint_init_unsigned(&out_val->data.x_bigint, size_in_bytes);
11111 return ira->codegen->builtin_types.entry_num_lit_int;11209 return ira->codegen->builtin_types.entry_num_lit_int;
11112 }11210 }
11113 }11211 }
...@@ -11213,10 +11311,10 @@ static TypeTableEntry *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionC...@@ -11213,10 +11311,10 @@ static TypeTableEntry *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionC
11213 return ira->codegen->builtin_types.entry_invalid;11311 return ira->codegen->builtin_types.entry_invalid;
11214 } else if (value->value.type->id == TypeTableEntryIdInt) {11312 } else if (value->value.type->id == TypeTableEntryIdInt) {
11215 if (value->value.special != ConstValSpecialRuntime) {11313 if (value->value.special != ConstValSpecialRuntime) {
11216 uint32_t result = bignum_ctz(&value->value.data.x_bignum,11314 size_t result = bigint_ctz(&value->value.data.x_bigint,
11217 value->value.type->data.integral.bit_count);11315 value->value.type->data.integral.bit_count);
11218 ConstExprValue *out_val = ir_build_const_from(ira, &ctz_instruction->base);11316 ConstExprValue *out_val = ir_build_const_from(ira, &ctz_instruction->base);
11219 bignum_init_unsigned(&out_val->data.x_bignum, result);11317 bigint_init_unsigned(&out_val->data.x_bigint, result);
11220 return value->value.type;11318 return value->value.type;
11221 }11319 }
1122211320
...@@ -11235,10 +11333,10 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC...@@ -11235,10 +11333,10 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC
11235 return ira->codegen->builtin_types.entry_invalid;11333 return ira->codegen->builtin_types.entry_invalid;
11236 } else if (value->value.type->id == TypeTableEntryIdInt) {11334 } else if (value->value.type->id == TypeTableEntryIdInt) {
11237 if (value->value.special != ConstValSpecialRuntime) {11335 if (value->value.special != ConstValSpecialRuntime) {
11238 uint32_t result = bignum_clz(&value->value.data.x_bignum,11336 size_t result = bigint_clz(&value->value.data.x_bigint,
11239 value->value.type->data.integral.bit_count);11337 value->value.type->data.integral.bit_count);
11240 ConstExprValue *out_val = ir_build_const_from(ira, &clz_instruction->base);11338 ConstExprValue *out_val = ir_build_const_from(ira, &clz_instruction->base);
11241 bignum_init_unsigned(&out_val->data.x_bignum, result);11339 bigint_init_unsigned(&out_val->data.x_bigint, result);
11242 return value->value.type;11340 return value->value.type;
11243 }11341 }
1124411342
...@@ -11272,7 +11370,7 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_...@@ -11272,7 +11370,7 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_
11272 source_instr->scope, source_instr->source_node);11370 source_instr->scope, source_instr->source_node);
11273 const_instruction->base.value.type = tag_type;11371 const_instruction->base.value.type = tag_type;
11274 const_instruction->base.value.special = ConstValSpecialStatic;11372 const_instruction->base.value.special = ConstValSpecialStatic;
11275 bignum_init_unsigned(&const_instruction->base.value.data.x_bignum, val->data.x_enum.tag);11373 bigint_init_unsigned(&const_instruction->base.value.data.x_bigint, val->data.x_enum.tag);
11276 return &const_instruction->base;11374 return &const_instruction->base;
11277 }11375 }
1127811376
...@@ -11441,7 +11539,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -11441,7 +11539,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
11441 TypeTableEntry *tag_type = target_type->data.enumeration.tag_type;11539 TypeTableEntry *tag_type = target_type->data.enumeration.tag_type;
11442 if (pointee_val) {11540 if (pointee_val) {
11443 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);11541 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
11444 bignum_init_unsigned(&out_val->data.x_bignum, pointee_val->data.x_enum.tag);11542 bigint_init_unsigned(&out_val->data.x_bigint, pointee_val->data.x_enum.tag);
11445 return tag_type;11543 return tag_type;
11446 }11544 }
1144711545
...@@ -11490,9 +11588,9 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr...@@ -11490,9 +11588,9 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
11490 if (!prong_val)11588 if (!prong_val)
11491 return ira->codegen->builtin_types.entry_invalid;11589 return ira->codegen->builtin_types.entry_invalid;
1149211590
11493 TypeEnumField *field = &target_type->data.enumeration.fields[prong_val->data.x_bignum.data.x_uint];11591 TypeEnumField *field;
11494 if (prong_value->value.type->id == TypeTableEntryIdEnumTag) {11592 if (prong_value->value.type->id == TypeTableEntryIdEnumTag) {
11495 field = &target_type->data.enumeration.fields[prong_val->data.x_bignum.data.x_uint];11593 field = &target_type->data.enumeration.fields[bigint_as_unsigned(&prong_val->data.x_bigint)];
11496 } else if (prong_value->value.type->id == TypeTableEntryIdEnum) {11594 } else if (prong_value->value.type->id == TypeTableEntryIdEnum) {
11497 field = &target_type->data.enumeration.fields[prong_val->data.x_enum.tag];11595 field = &target_type->data.enumeration.fields[prong_val->data.x_enum.tag];
11498 } else {11596 } else {
...@@ -11619,7 +11717,7 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,...@@ -11619,7 +11717,7 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,
11619 ConstExprValue *len_val = &array_value->value.data.x_struct.fields[slice_len_index];11717 ConstExprValue *len_val = &array_value->value.data.x_struct.fields[slice_len_index];
11620 if (len_val->special != ConstValSpecialRuntime) {11718 if (len_val->special != ConstValSpecialRuntime) {
11621 return ir_analyze_const_usize(ira, &array_len_instruction->base,11719 return ir_analyze_const_usize(ira, &array_len_instruction->base,
11622 len_val->data.x_bignum.data.x_uint);11720 bigint_as_unsigned(&len_val->data.x_bigint));
11623 }11721 }
11624 }11722 }
11625 TypeStructField *field = &type_entry->data.structure.fields[slice_len_index];11723 TypeStructField *field = &type_entry->data.structure.fields[slice_len_index];
...@@ -11866,7 +11964,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira...@@ -11866,7 +11964,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
1186611964
11867 TypeTableEntry *enum_type = container_type_value->value.type->data.enum_tag.enum_type;11965 TypeTableEntry *enum_type = container_type_value->value.type->data.enum_tag.enum_type;
1186811966
11869 uint64_t tag_uint = tag_value->data.x_bignum.data.x_uint;11967 uint64_t tag_uint = bigint_as_unsigned(&tag_value->data.x_bigint);
11870 TypeEnumField *field = &enum_type->data.enumeration.fields[tag_uint];11968 TypeEnumField *field = &enum_type->data.enumeration.fields[tag_uint];
11871 TypeTableEntry *this_field_type = field->type_entry;11969 TypeTableEntry *this_field_type = field->type_entry;
1187211970
...@@ -12063,7 +12161,7 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn...@@ -12063,7 +12161,7 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn
1206312161
12064 if (instr_is_comptime(target)) {12162 if (instr_is_comptime(target)) {
12065 TypeTableEntry *enum_type = target->value.type->data.enum_tag.enum_type;12163 TypeTableEntry *enum_type = target->value.type->data.enum_tag.enum_type;
12066 uint64_t tag_value = target->value.data.x_bignum.data.x_uint;12164 uint64_t tag_value = bigint_as_unsigned(&target->value.data.x_bigint);
12067 TypeEnumField *field = &enum_type->data.enumeration.fields[tag_value];12165 TypeEnumField *field = &enum_type->data.enumeration.fields[tag_value];
12068 ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);12166 ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);
12069 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);12167 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
...@@ -12197,7 +12295,7 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira,...@@ -12197,7 +12295,7 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira,
1219712295
12198 size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, container_type->type_ref, field->gen_index);12296 size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, container_type->type_ref, field->gen_index);
12199 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);12297 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
12200 bignum_init_unsigned(&out_val->data.x_bignum, byte_offset);12298 bigint_init_unsigned(&out_val->data.x_bigint, byte_offset);
12201 return ira->codegen->builtin_types.entry_num_lit_int;12299 return ira->codegen->builtin_types.entry_num_lit_int;
12202}12300}
1220312301
...@@ -12506,8 +12604,8 @@ static TypeTableEntry *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruc...@@ -12506,8 +12604,8 @@ static TypeTableEntry *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruc
1250612604
12507 if (target->value.special == ConstValSpecialStatic) {12605 if (target->value.special == ConstValSpecialStatic) {
12508 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);12606 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
12509 bignum_init_bignum(&out_val->data.x_bignum, &target->value.data.x_bignum);12607 bigint_truncate(&out_val->data.x_bigint, &target->value.data.x_bigint, dest_type->data.integral.bit_count,
12510 bignum_truncate(&out_val->data.x_bignum, dest_type->data.integral.bit_count);12608 dest_type->data.integral.is_signed);
12511 return dest_type;12609 return dest_type;
12512 }12610 }
1251312611
...@@ -12619,7 +12717,7 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi...@@ -12619,7 +12717,7 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi
12619 zig_unreachable();12717 zig_unreachable();
12620 }12718 }
1262112719
12622 size_t count = casted_count->value.data.x_bignum.data.x_uint;12720 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);
12623 size_t end = start + count;12721 size_t end = start + count;
12624 if (end > bound_end) {12722 if (end > bound_end) {
12625 ir_add_error(ira, count_value, buf_sprintf("out of bounds pointer access"));12723 ir_add_error(ira, count_value, buf_sprintf("out of bounds pointer access"));
...@@ -12681,7 +12779,7 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi...@@ -12681,7 +12779,7 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi
12681 casted_count->value.special == ConstValSpecialStatic &&12779 casted_count->value.special == ConstValSpecialStatic &&
12682 casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr)12780 casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr)
12683 {12781 {
12684 size_t count = casted_count->value.data.x_bignum.data.x_uint;12782 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);
1268512783
12686 ConstExprValue *dest_ptr_val = &casted_dest_ptr->value;12784 ConstExprValue *dest_ptr_val = &casted_dest_ptr->value;
12687 ConstExprValue *dest_elements;12785 ConstExprValue *dest_elements;
...@@ -12868,21 +12966,21 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio...@@ -12868,21 +12966,21 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
12868 case ConstPtrSpecialBaseArray:12966 case ConstPtrSpecialBaseArray:
12869 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;12967 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
12870 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;12968 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
12871 rel_end = len_val->data.x_bignum.data.x_uint;12969 rel_end = bigint_as_unsigned(&len_val->data.x_bigint);
12872 break;12970 break;
12873 case ConstPtrSpecialBaseStruct:12971 case ConstPtrSpecialBaseStruct:
12874 zig_panic("TODO slice const inner struct");12972 zig_panic("TODO slice const inner struct");
12875 case ConstPtrSpecialHardCodedAddr:12973 case ConstPtrSpecialHardCodedAddr:
12876 array_val = nullptr;12974 array_val = nullptr;
12877 abs_offset = 0;12975 abs_offset = 0;
12878 rel_end = len_val->data.x_bignum.data.x_uint;12976 rel_end = bigint_as_unsigned(&len_val->data.x_bigint);
12879 break;12977 break;
12880 }12978 }
12881 } else {12979 } else {
12882 zig_unreachable();12980 zig_unreachable();
12883 }12981 }
1288412982
12885 uint64_t start_scalar = casted_start->value.data.x_bignum.data.x_uint;12983 uint64_t start_scalar = bigint_as_unsigned(&casted_start->value.data.x_bigint);
12886 if (start_scalar > rel_end) {12984 if (start_scalar > rel_end) {
12887 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));12985 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
12888 return ira->codegen->builtin_types.entry_invalid;12986 return ira->codegen->builtin_types.entry_invalid;
...@@ -12890,7 +12988,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio...@@ -12890,7 +12988,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
1289012988
12891 uint64_t end_scalar;12989 uint64_t end_scalar;
12892 if (end) {12990 if (end) {
12893 end_scalar = end->value.data.x_bignum.data.x_uint;12991 end_scalar = bigint_as_unsigned(&end->value.data.x_bigint);
12894 } else {12992 } else {
12895 end_scalar = rel_end;12993 end_scalar = rel_end;
12896 }12994 }
...@@ -12970,7 +13068,7 @@ static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrIns...@@ -12970,7 +13068,7 @@ static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrIns
12970 }13068 }
1297113069
12972 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);13070 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
12973 bignum_init_unsigned(&out_val->data.x_bignum, result);13071 bigint_init_unsigned(&out_val->data.x_bigint, result);
12974 return ira->codegen->builtin_types.entry_num_lit_int;13072 return ira->codegen->builtin_types.entry_num_lit_int;
12975}13073}
1297613074
...@@ -13011,7 +13109,7 @@ static TypeTableEntry *ir_analyze_instruction_alignof(IrAnalyze *ira, IrInstruct...@@ -13011,7 +13109,7 @@ static TypeTableEntry *ir_analyze_instruction_alignof(IrAnalyze *ira, IrInstruct
13011 } else {13109 } else {
13012 uint64_t align_in_bytes = LLVMABIAlignmentOfType(ira->codegen->target_data_ref, type_entry->type_ref);13110 uint64_t align_in_bytes = LLVMABIAlignmentOfType(ira->codegen->target_data_ref, type_entry->type_ref);
13013 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);13111 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13014 bignum_init_unsigned(&out_val->data.x_bignum, align_in_bytes);13112 bigint_init_unsigned(&out_val->data.x_bigint, align_in_bytes);
13015 return ira->codegen->builtin_types.entry_num_lit_int;13113 return ira->codegen->builtin_types.entry_num_lit_int;
13016 }13114 }
13017}13115}
...@@ -13060,29 +13158,32 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst...@@ -13060,29 +13158,32 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst
13060 casted_result_ptr->value.special == ConstValSpecialStatic)13158 casted_result_ptr->value.special == ConstValSpecialStatic)
13061 {13159 {
13062 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);13160 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13063 BigNum *op1_bignum = &casted_op1->value.data.x_bignum;13161 BigInt *op1_bigint = &casted_op1->value.data.x_bigint;
13064 BigNum *op2_bignum = &casted_op2->value.data.x_bignum;13162 BigInt *op2_bigint = &casted_op2->value.data.x_bigint;
13065 ConstExprValue *pointee_val = const_ptr_pointee(ira->codegen, &casted_result_ptr->value);13163 ConstExprValue *pointee_val = const_ptr_pointee(ira->codegen, &casted_result_ptr->value);
13066 BigNum *dest_bignum = &pointee_val->data.x_bignum;13164 BigInt *dest_bigint = &pointee_val->data.x_bigint;
13067 switch (instruction->op) {13165 switch (instruction->op) {
13068 case IrOverflowOpAdd:13166 case IrOverflowOpAdd:
13069 out_val->data.x_bool = bignum_add(dest_bignum, op1_bignum, op2_bignum);13167 bigint_add(dest_bigint, op1_bigint, op2_bigint);
13070 break;13168 break;
13071 case IrOverflowOpSub:13169 case IrOverflowOpSub:
13072 out_val->data.x_bool = bignum_sub(dest_bignum, op1_bignum, op2_bignum);13170 bigint_sub(dest_bigint, op1_bigint, op2_bigint);
13073 break;13171 break;
13074 case IrOverflowOpMul:13172 case IrOverflowOpMul:
13075 out_val->data.x_bool = bignum_mul(dest_bignum, op1_bignum, op2_bignum);13173 bigint_mul(dest_bigint, op1_bigint, op2_bigint);
13076 break;13174 break;
13077 case IrOverflowOpShl:13175 case IrOverflowOpShl:
13078 out_val->data.x_bool = bignum_shl(dest_bignum, op1_bignum, op2_bignum);13176 bigint_shl(dest_bigint, op1_bigint, op2_bigint);
13079 break;13177 break;
13080 }13178 }
13081 if (!bignum_fits_in_bits(dest_bignum, dest_type->data.integral.bit_count,13179 if (!bigint_fits_in_bits(dest_bigint, dest_type->data.integral.bit_count,
13082 dest_type->data.integral.is_signed))13180 dest_type->data.integral.is_signed))
13083 {13181 {
13084 out_val->data.x_bool = true;13182 out_val->data.x_bool = true;
13085 bignum_truncate(dest_bignum, dest_type->data.integral.bit_count);13183 BigInt tmp_bigint;
13184 bigint_init_bigint(&tmp_bigint, dest_bigint);
13185 bigint_truncate(dest_bigint, &tmp_bigint, dest_type->data.integral.bit_count,
13186 dest_type->data.integral.is_signed);
13086 }13187 }
13087 pointee_val->special = ConstValSpecialStatic;13188 pointee_val->special = ConstValSpecialStatic;
13088 return ira->codegen->builtin_types.entry_bool;13189 return ira->codegen->builtin_types.entry_bool;
...@@ -13301,14 +13402,14 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira...@@ -13301,14 +13402,14 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
13301 size_t start_index;13402 size_t start_index;
13302 size_t end_index;13403 size_t end_index;
13303 if (start_value->value.type->id == TypeTableEntryIdEnumTag) {13404 if (start_value->value.type->id == TypeTableEntryIdEnumTag) {
13304 start_index = start_value->value.data.x_bignum.data.x_uint;13405 start_index = bigint_as_unsigned(&start_value->value.data.x_bigint);
13305 } else if (start_value->value.type->id == TypeTableEntryIdEnum) {13406 } else if (start_value->value.type->id == TypeTableEntryIdEnum) {
13306 start_index = start_value->value.data.x_enum.tag;13407 start_index = start_value->value.data.x_enum.tag;
13307 } else {13408 } else {
13308 zig_unreachable();13409 zig_unreachable();
13309 }13410 }
13310 if (end_value->value.type->id == TypeTableEntryIdEnumTag) {13411 if (end_value->value.type->id == TypeTableEntryIdEnumTag) {
13311 end_index = end_value->value.data.x_bignum.data.x_uint;13412 end_index = bigint_as_unsigned(&end_value->value.data.x_bigint);
13312 } else if (end_value->value.type->id == TypeTableEntryIdEnum) {13413 } else if (end_value->value.type->id == TypeTableEntryIdEnum) {
13313 end_index = end_value->value.data.x_enum.tag;13414 end_index = end_value->value.data.x_enum.tag;
13314 } else {13415 } else {
...@@ -13357,7 +13458,7 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira...@@ -13357,7 +13458,7 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
13357 if (!end_val)13458 if (!end_val)
13358 return ira->codegen->builtin_types.entry_invalid;13459 return ira->codegen->builtin_types.entry_invalid;
1335913460
13360 AstNode *prev_node = rangeset_add_range(&rs, &start_val->data.x_bignum, &end_val->data.x_bignum,13461 AstNode *prev_node = rangeset_add_range(&rs, &start_val->data.x_bigint, &end_val->data.x_bigint,
13361 start_value->source_node);13462 start_value->source_node);
13362 if (prev_node != nullptr) {13463 if (prev_node != nullptr) {
13363 ErrorMsg *msg = ir_add_error(ira, start_value, buf_sprintf("duplicate switch value"));13464 ErrorMsg *msg = ir_add_error(ira, start_value, buf_sprintf("duplicate switch value"));
...@@ -13366,9 +13467,9 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira...@@ -13366,9 +13467,9 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
13366 }13467 }
13367 }13468 }
13368 if (!instruction->have_else_prong) {13469 if (!instruction->have_else_prong) {
13369 BigNum min_val;13470 BigInt min_val;
13370 eval_min_max_value_int(ira->codegen, switch_type, &min_val, false);13471 eval_min_max_value_int(ira->codegen, switch_type, &min_val, false);
13371 BigNum max_val;13472 BigInt max_val;
13372 eval_min_max_value_int(ira->codegen, switch_type, &max_val, true);13473 eval_min_max_value_int(ira->codegen, switch_type, &max_val, true);
13373 if (!rangeset_spans(&rs, &min_val, &max_val)) {13474 if (!rangeset_spans(&rs, &min_val, &max_val)) {
13374 ir_add_error(ira, &instruction->base, buf_sprintf("switch must handle all possibilities"));13475 ir_add_error(ira, &instruction->base, buf_sprintf("switch must handle all possibilities"));
...@@ -13503,16 +13604,18 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -13503,16 +13604,18 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
13503 buf[0] = val->data.x_bool ? 1 : 0;13604 buf[0] = val->data.x_bool ? 1 : 0;
13504 return;13605 return;
13505 case TypeTableEntryIdInt:13606 case TypeTableEntryIdInt:
13506 bignum_write_twos_complement(&val->data.x_bignum, buf, val->type->data.integral.bit_count, codegen->is_big_endian);13607 bigint_write_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
13608 codegen->is_big_endian);
13507 return;13609 return;
13508 case TypeTableEntryIdFloat:13610 case TypeTableEntryIdFloat:
13509 bignum_write_ieee597(&val->data.x_bignum, buf, val->type->data.floating.bit_count, codegen->is_big_endian);13611 bigfloat_write_ieee597(&val->data.x_bigfloat, buf, val->type->data.floating.bit_count,
13612 codegen->is_big_endian);
13510 return;13613 return;
13511 case TypeTableEntryIdPointer:13614 case TypeTableEntryIdPointer:
13512 if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {13615 if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
13513 BigNum bn;13616 BigInt bn;
13514 bignum_init_unsigned(&bn, val->data.x_ptr.data.hard_coded_addr.addr);13617 bigint_init_unsigned(&bn, val->data.x_ptr.data.hard_coded_addr.addr);
13515 bignum_write_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, codegen->is_big_endian);13618 bigint_write_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, codegen->is_big_endian);
13516 return;13619 return;
13517 } else {13620 } else {
13518 zig_unreachable();13621 zig_unreachable();
...@@ -13562,18 +13665,20 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -13562,18 +13665,20 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
13562 val->data.x_bool = (buf[0] != 0);13665 val->data.x_bool = (buf[0] != 0);
13563 return;13666 return;
13564 case TypeTableEntryIdInt:13667 case TypeTableEntryIdInt:
13565 bignum_read_twos_complement(&val->data.x_bignum, buf, val->type->data.integral.bit_count, codegen->is_big_endian,13668 bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
13566 val->type->data.integral.is_signed);13669 codegen->is_big_endian, val->type->data.integral.is_signed);
13567 return;13670 return;
13568 case TypeTableEntryIdFloat:13671 case TypeTableEntryIdFloat:
13569 bignum_read_ieee597(&val->data.x_bignum, buf, val->type->data.floating.bit_count, codegen->is_big_endian);13672 bigfloat_read_ieee597(&val->data.x_bigfloat, buf, val->type->data.floating.bit_count,
13673 codegen->is_big_endian);
13570 return;13674 return;
13571 case TypeTableEntryIdPointer:13675 case TypeTableEntryIdPointer:
13572 {13676 {
13573 val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;13677 val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
13574 BigNum bn;13678 BigInt bn;
13575 bignum_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, codegen->is_big_endian, false);13679 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,
13576 val->data.x_ptr.data.hard_coded_addr.addr = bignum_to_twos_complement(&bn);13680 codegen->is_big_endian, false);
13681 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
13577 return;13682 return;
13578 }13683 }
13579 case TypeTableEntryIdArray:13684 case TypeTableEntryIdArray:
...@@ -13729,7 +13834,7 @@ static TypeTableEntry *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstr...@@ -13729,7 +13834,7 @@ static TypeTableEntry *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstr
1372913834
13730 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);13835 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13731 out_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;13836 out_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
13732 out_val->data.x_ptr.data.hard_coded_addr.addr = bignum_to_twos_complement(&val->data.x_bignum);13837 out_val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
13733 return dest_type;13838 return dest_type;
13734 }13839 }
1373513840
src/os.hpp+1
...@@ -13,6 +13,7 @@...@@ -13,6 +13,7 @@
13#include "error.hpp"13#include "error.hpp"
1414
15#include <stdio.h>15#include <stdio.h>
16#include <inttypes.h>
1617
17enum TerminationId {18enum TerminationId {
18 TerminationIdClean,19 TerminationIdClean,
src/parser.cpp+22-9
...@@ -186,9 +186,14 @@ static Buf *token_buf(Token *token) {...@@ -186,9 +186,14 @@ static Buf *token_buf(Token *token) {
186 return &token->data.str_lit.str;186 return &token->data.str_lit.str;
187}187}
188188
189static BigNum *token_bignum(Token *token) {189static BigInt *token_bigint(Token *token) {
190 assert(token->id == TokenIdNumberLiteral);190 assert(token->id == TokenIdIntLiteral);
191 return &token->data.num_lit.bignum;191 return &token->data.int_lit.bigint;
192}
193
194static BigFloat *token_bigfloat(Token *token) {
195 assert(token->id == TokenIdFloatLiteral);
196 return &token->data.float_lit.bigfloat;
192}197}
193198
194static uint8_t token_char_lit(Token *token) {199static uint8_t token_char_lit(Token *token) {
...@@ -660,16 +665,21 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b...@@ -660,16 +665,21 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
660}665}
661666
662/*667/*
663PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl668PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
664KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"669KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"
665*/670*/
666static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {671static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
667 Token *token = &pc->tokens->at(*token_index);672 Token *token = &pc->tokens->at(*token_index);
668673
669 if (token->id == TokenIdNumberLiteral) {674 if (token->id == TokenIdIntLiteral) {
670 AstNode *node = ast_create_node(pc, NodeTypeNumberLiteral, token);675 AstNode *node = ast_create_node(pc, NodeTypeIntLiteral, token);
671 node->data.number_literal.bignum = token_bignum(token);676 node->data.int_literal.bigint = token_bigint(token);
672 node->data.number_literal.overflow = token->data.num_lit.overflow;677 *token_index += 1;
678 return node;
679 } else if (token->id == TokenIdFloatLiteral) {
680 AstNode *node = ast_create_node(pc, NodeTypeFloatLiteral, token);
681 node->data.float_literal.bigfloat = token_bigfloat(token);
682 node->data.float_literal.overflow = token->data.float_lit.overflow;
673 *token_index += 1;683 *token_index += 1;
674 return node;684 return node;
675 } else if (token->id == TokenIdStringLiteral) {685 } else if (token->id == TokenIdStringLiteral) {
...@@ -2629,7 +2639,10 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2629,7 +2639,10 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2629 visit_field(&node->data.unwrap_err_expr.symbol, visit, context);2639 visit_field(&node->data.unwrap_err_expr.symbol, visit, context);
2630 visit_field(&node->data.unwrap_err_expr.op2, visit, context);2640 visit_field(&node->data.unwrap_err_expr.op2, visit, context);
2631 break;2641 break;
2632 case NodeTypeNumberLiteral:2642 case NodeTypeIntLiteral:
2643 // none
2644 break;
2645 case NodeTypeFloatLiteral:
2633 // none2646 // none
2634 break;2647 break;
2635 case NodeTypeStringLiteral:2648 case NodeTypeStringLiteral:
src/range_set.cpp+15-17
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1#include "range_set.hpp"1#include "range_set.hpp"
22
3AstNode *rangeset_add_range(RangeSet *rs, BigNum *first, BigNum *last, AstNode *source_node) {3AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode *source_node) {
4 for (size_t i = 0; i < rs->src_range_list.length; i += 1) {4 for (size_t i = 0; i < rs->src_range_list.length; i += 1) {
5 RangeWithSrc *range_with_src = &rs->src_range_list.at(i);5 RangeWithSrc *range_with_src = &rs->src_range_list.at(i);
6 Range *range = &range_with_src->range;6 Range *range = &range_with_src->range;
7 if ((bignum_cmp_gte(first, &range->first) && bignum_cmp_lte(first, &range->last)) ||7 if ((bigint_cmp(first, &range->first) != CmpLT && bigint_cmp(first, &range->last) != CmpGT) ||
8 (bignum_cmp_gte(last, &range->first) && bignum_cmp_lte(last, &range->last)))8 (bigint_cmp(last, &range->first) != CmpLT && bigint_cmp(last, &range->last) != CmpGT))
9 {9 {
10 return range_with_src->source_node;10 return range_with_src->source_node;
11 }11 }
...@@ -16,24 +16,22 @@ AstNode *rangeset_add_range(RangeSet *rs, BigNum *first, BigNum *last, AstNode *...@@ -16,24 +16,22 @@ AstNode *rangeset_add_range(RangeSet *rs, BigNum *first, BigNum *last, AstNode *
1616
17}17}
1818
19static bool add_range(ZigList<Range> *list, Range *new_range, BigNum *one) {19static bool add_range(ZigList<Range> *list, Range *new_range, BigInt *one) {
20 for (size_t i = 0; i < list->length; i += 1) {20 for (size_t i = 0; i < list->length; i += 1) {
21 Range *range = &list->at(i);21 Range *range = &list->at(i);
2222
23 BigNum first_minus_one;23 BigInt first_minus_one;
24 if (bignum_sub(&first_minus_one, &range->first, one))24 bigint_sub(&first_minus_one, &range->first, one);
25 zig_unreachable();
2625
27 if (bignum_cmp_eq(&new_range->last, &first_minus_one)) {26 if (bigint_cmp(&new_range->last, &first_minus_one) == CmpEQ) {
28 range->first = new_range->first;27 range->first = new_range->first;
29 return true;28 return true;
30 }29 }
3130
32 BigNum last_plus_one;31 BigInt last_plus_one;
33 if (bignum_add(&last_plus_one, &range->last, one))32 bigint_add(&last_plus_one, &range->last, one);
34 zig_unreachable();
3533
36 if (bignum_cmp_eq(&new_range->first, &last_plus_one)) {34 if (bigint_cmp(&new_range->first, &last_plus_one) == CmpEQ) {
37 range->last = new_range->last;35 range->last = new_range->last;
38 return true;36 return true;
39 }37 }
...@@ -42,7 +40,7 @@ static bool add_range(ZigList<Range> *list, Range *new_range, BigNum *one) {...@@ -42,7 +40,7 @@ static bool add_range(ZigList<Range> *list, Range *new_range, BigNum *one) {
42 return false;40 return false;
43}41}
4442
45bool rangeset_spans(RangeSet *rs, BigNum *first, BigNum *last) {43bool rangeset_spans(RangeSet *rs, BigInt *first, BigInt *last) {
46 ZigList<Range> cur_list_value = {0};44 ZigList<Range> cur_list_value = {0};
47 ZigList<Range> other_list_value = {0};45 ZigList<Range> other_list_value = {0};
48 ZigList<Range> *cur_list = &cur_list_value;46 ZigList<Range> *cur_list = &cur_list_value;
...@@ -54,8 +52,8 @@ bool rangeset_spans(RangeSet *rs, BigNum *first, BigNum *last) {...@@ -54,8 +52,8 @@ bool rangeset_spans(RangeSet *rs, BigNum *first, BigNum *last) {
54 cur_list->append({range->first, range->last});52 cur_list->append({range->first, range->last});
55 }53 }
5654
57 BigNum one;55 BigInt one;
58 bignum_init_unsigned(&one, 1);56 bigint_init_unsigned(&one, 1);
5957
60 bool changes_made = true;58 bool changes_made = true;
61 while (changes_made) {59 while (changes_made) {
...@@ -73,9 +71,9 @@ bool rangeset_spans(RangeSet *rs, BigNum *first, BigNum *last) {...@@ -73,9 +71,9 @@ bool rangeset_spans(RangeSet *rs, BigNum *first, BigNum *last) {
73 if (cur_list->length != 1)71 if (cur_list->length != 1)
74 return false;72 return false;
75 Range *range = &cur_list->at(0);73 Range *range = &cur_list->at(0);
76 if (bignum_cmp_neq(&range->first, first))74 if (bigint_cmp(&range->first, first) != CmpEQ)
77 return false;75 return false;
78 if (bignum_cmp_neq(&range->last, last))76 if (bigint_cmp(&range->last, last) != CmpEQ)
79 return false;77 return false;
80 return true;78 return true;
81}79}
src/range_set.hpp+4-4
...@@ -11,8 +11,8 @@...@@ -11,8 +11,8 @@
11#include "all_types.hpp"11#include "all_types.hpp"
1212
13struct Range {13struct Range {
14 BigNum first;14 BigInt first;
15 BigNum last;15 BigInt last;
16};16};
1717
18struct RangeWithSrc {18struct RangeWithSrc {
...@@ -24,7 +24,7 @@ struct RangeSet {...@@ -24,7 +24,7 @@ struct RangeSet {
24 ZigList<RangeWithSrc> src_range_list;24 ZigList<RangeWithSrc> src_range_list;
25};25};
2626
27AstNode *rangeset_add_range(RangeSet *rs, BigNum *first, BigNum *last, AstNode *source_node);27AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode *source_node);
28bool rangeset_spans(RangeSet *rs, BigNum *first, BigNum *last);28bool rangeset_spans(RangeSet *rs, BigInt *first, BigInt *last);
2929
30#endif30#endif
src/tokenizer.cpp+87-58
...@@ -225,13 +225,13 @@ struct Tokenize {...@@ -225,13 +225,13 @@ struct Tokenize {
225 uint32_t radix;225 uint32_t radix;
226 int32_t exp_add_amt;226 int32_t exp_add_amt;
227 bool is_exp_negative;227 bool is_exp_negative;
228 bool is_num_lit_float;
229 size_t char_code_index;228 size_t char_code_index;
230 size_t char_code_end;229 size_t char_code_end;
231 bool unicode;230 bool unicode;
232 uint32_t char_code;231 uint32_t char_code;
233 int exponent_in_bin_or_dec;232 int exponent_in_bin_or_dec;
234 BigNum specified_exponent;233 BigInt specified_exponent;
234 BigInt significand;
235};235};
236236
237__attribute__ ((format (printf, 2, 3)))237__attribute__ ((format (printf, 2, 3)))
...@@ -255,8 +255,11 @@ static void tokenize_error(Tokenize *t, const char *format, ...) {...@@ -255,8 +255,11 @@ static void tokenize_error(Tokenize *t, const char *format, ...) {
255static void set_token_id(Tokenize *t, Token *token, TokenId id) {255static void set_token_id(Tokenize *t, Token *token, TokenId id) {
256 token->id = id;256 token->id = id;
257257
258 if (id == TokenIdNumberLiteral) {258 if (id == TokenIdIntLiteral) {
259 token->data.num_lit.overflow = false;259 bigint_init_unsigned(&token->data.int_lit.bigint, 0);
260 } else if (id == TokenIdFloatLiteral) {
261 bigfloat_init_float(&token->data.float_lit.bigfloat, 0.0);
262 token->data.float_lit.overflow = false;
260 } else if (id == TokenIdStringLiteral || id == TokenIdSymbol) {263 } else if (id == TokenIdStringLiteral || id == TokenIdSymbol) {
261 memset(&token->data.str_lit.str, 0, sizeof(Buf));264 memset(&token->data.str_lit.str, 0, sizeof(Buf));
262 buf_resize(&token->data.str_lit.str, 0);265 buf_resize(&token->data.str_lit.str, 0);
...@@ -283,34 +286,40 @@ static void cancel_token(Tokenize *t) {...@@ -283,34 +286,40 @@ static void cancel_token(Tokenize *t) {
283}286}
284287
285static void end_float_token(Tokenize *t) {288static void end_float_token(Tokenize *t) {
286 t->cur_tok->data.num_lit.bignum.kind = BigNumKindFloat;
287
288 if (t->radix == 10) {289 if (t->radix == 10) {
289 char *str_begin = buf_ptr(t->buf) + t->cur_tok->start_pos;290 uint8_t *ptr_buf = (uint8_t*)buf_ptr(t->buf) + t->cur_tok->start_pos;
290 char *str_end;291 size_t buf_len = t->cur_tok->end_pos - t->cur_tok->start_pos;
291 errno = 0;292 if (bigfloat_init_buf_base10(&t->cur_tok->data.float_lit.bigfloat, ptr_buf, buf_len)) {
292 t->cur_tok->data.num_lit.bignum.data.x_float = strtod(str_begin, &str_end);293 t->cur_tok->data.float_lit.overflow = true;
293 if (errno) {
294 t->cur_tok->data.num_lit.overflow = true;
295 return;
296 }294 }
297 assert(str_end <= buf_ptr(t->buf) + t->cur_tok->end_pos);
298 return;295 return;
299 }296 }
300297
298 BigInt int_max;
299 bigint_init_unsigned(&int_max, INT_MAX);
300
301 if (bigint_cmp(&t->specified_exponent, &int_max) != CmpLT) {
302 t->cur_tok->data.float_lit.overflow = true;
303 return;
304 }
301305
302 if (t->specified_exponent.data.x_uint >= INT_MAX) {306 if (!bigint_fits_in_bits(&t->specified_exponent, 64, true)) {
303 t->cur_tok->data.num_lit.overflow = true;307 t->cur_tok->data.float_lit.overflow = true;
304 return;308 return;
305 }309 }
306310
307 int64_t specified_exponent = t->specified_exponent.data.x_uint;311 int64_t specified_exponent = bigint_as_signed(&t->specified_exponent);
308 if (t->is_exp_negative) {312 if (t->is_exp_negative) {
309 specified_exponent = -specified_exponent;313 specified_exponent = -specified_exponent;
310 }314 }
311 t->exponent_in_bin_or_dec = (int)(t->exponent_in_bin_or_dec + specified_exponent);315 t->exponent_in_bin_or_dec = (int)(t->exponent_in_bin_or_dec + specified_exponent);
312316
313 uint64_t significand = t->cur_tok->data.num_lit.bignum.data.x_uint;317 if (!bigint_fits_in_bits(&t->significand, 64, false)) {
318 t->cur_tok->data.float_lit.overflow = true;
319 return;
320 }
321
322 uint64_t significand = bigint_as_unsigned(&t->significand);
314 uint64_t significand_bits;323 uint64_t significand_bits;
315 uint64_t exponent_bits;324 uint64_t exponent_bits;
316 if (significand == 0) {325 if (significand == 0) {
...@@ -325,7 +334,7 @@ static void end_float_token(Tokenize *t) {...@@ -325,7 +334,7 @@ static void end_float_token(Tokenize *t) {
325 int significand_magnitude_in_bin = __builtin_clzll(1) - __builtin_clzll(significand);334 int significand_magnitude_in_bin = __builtin_clzll(1) - __builtin_clzll(significand);
326 t->exponent_in_bin_or_dec += significand_magnitude_in_bin;335 t->exponent_in_bin_or_dec += significand_magnitude_in_bin;
327 if (!(-1023 <= t->exponent_in_bin_or_dec && t->exponent_in_bin_or_dec < 1023)) {336 if (!(-1023 <= t->exponent_in_bin_or_dec && t->exponent_in_bin_or_dec < 1023)) {
328 t->cur_tok->data.num_lit.overflow = true;337 t->cur_tok->data.float_lit.overflow = true;
329 return;338 return;
330 } else {339 } else {
331 // this should chop off exactly one 1 bit from the top.340 // this should chop off exactly one 1 bit from the top.
...@@ -335,20 +344,17 @@ static void end_float_token(Tokenize *t) {...@@ -335,20 +344,17 @@ static void end_float_token(Tokenize *t) {
335 }344 }
336 }345 }
337 uint64_t double_bits = (exponent_bits << 52) | significand_bits;346 uint64_t double_bits = (exponent_bits << 52) | significand_bits;
338 safe_memcpy(&t->cur_tok->data.num_lit.bignum.data.x_float, (double *)&double_bits, 1);347 double dbl_value;
348 safe_memcpy(&dbl_value, (double *)&double_bits, 1);
349 bigfloat_init_float(&t->cur_tok->data.float_lit.bigfloat, dbl_value);
339}350}
340351
341static void end_token(Tokenize *t) {352static void end_token(Tokenize *t) {
342 assert(t->cur_tok);353 assert(t->cur_tok);
343 t->cur_tok->end_pos = t->pos + 1;354 t->cur_tok->end_pos = t->pos + 1;
344355
345 if (t->cur_tok->id == TokenIdNumberLiteral) {356 if (t->cur_tok->id == TokenIdFloatLiteral) {
346 if (t->cur_tok->data.num_lit.overflow) {357 end_float_token(t);
347 return;
348 }
349 if (t->is_num_lit_float) {
350 end_float_token(t);
351 }
352 } else if (t->cur_tok->id == TokenIdSymbol) {358 } else if (t->cur_tok->id == TokenIdSymbol) {
353 char *token_mem = buf_ptr(t->buf) + t->cur_tok->start_pos;359 char *token_mem = buf_ptr(t->buf) + t->cur_tok->start_pos;
354 int token_len = (int)(t->cur_tok->end_pos - t->cur_tok->start_pos);360 int token_len = (int)(t->cur_tok->end_pos - t->cur_tok->start_pos);
...@@ -428,23 +434,21 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -428,23 +434,21 @@ void tokenize(Buf *buf, Tokenization *out) {
428 break;434 break;
429 case '0':435 case '0':
430 t.state = TokenizeStateZero;436 t.state = TokenizeStateZero;
431 begin_token(&t, TokenIdNumberLiteral);437 begin_token(&t, TokenIdIntLiteral);
432 t.radix = 10;438 t.radix = 10;
433 t.exp_add_amt = 1;439 t.exp_add_amt = 1;
434 t.exponent_in_bin_or_dec = 0;440 t.exponent_in_bin_or_dec = 0;
435 t.is_num_lit_float = false;441 bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, 0);
436 bignum_init_unsigned(&t.cur_tok->data.num_lit.bignum, 0);442 bigint_init_unsigned(&t.specified_exponent, 0);
437 bignum_init_unsigned(&t.specified_exponent, 0);
438 break;443 break;
439 case DIGIT_NON_ZERO:444 case DIGIT_NON_ZERO:
440 t.state = TokenizeStateNumber;445 t.state = TokenizeStateNumber;
441 begin_token(&t, TokenIdNumberLiteral);446 begin_token(&t, TokenIdIntLiteral);
442 t.radix = 10;447 t.radix = 10;
443 t.exp_add_amt = 1;448 t.exp_add_amt = 1;
444 t.exponent_in_bin_or_dec = 0;449 t.exponent_in_bin_or_dec = 0;
445 t.is_num_lit_float = false;450 bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, get_digit_value(c));
446 bignum_init_unsigned(&t.cur_tok->data.num_lit.bignum, get_digit_value(c));451 bigint_init_unsigned(&t.specified_exponent, 0);
447 bignum_init_unsigned(&t.specified_exponent, 0);
448 break;452 break;
449 case '"':453 case '"':
450 begin_token(&t, TokenIdStringLiteral);454 begin_token(&t, TokenIdStringLiteral);
...@@ -1182,7 +1186,9 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1182,7 +1186,9 @@ void tokenize(Buf *buf, Tokenization *out) {
1182 }1186 }
1183 if (is_exponent_signifier(c, t.radix)) {1187 if (is_exponent_signifier(c, t.radix)) {
1184 t.state = TokenizeStateFloatExponentUnsigned;1188 t.state = TokenizeStateFloatExponentUnsigned;
1185 t.is_num_lit_float = true;1189 assert(t.cur_tok->id == TokenIdIntLiteral);
1190 bigint_init_bigint(&t.significand, &t.cur_tok->data.int_lit.bigint);
1191 set_token_id(&t, t.cur_tok, TokenIdFloatLiteral);
1186 break;1192 break;
1187 }1193 }
1188 uint32_t digit_value = get_digit_value(c);1194 uint32_t digit_value = get_digit_value(c);
...@@ -1196,23 +1202,33 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1196,23 +1202,33 @@ void tokenize(Buf *buf, Tokenization *out) {
1196 t.state = TokenizeStateStart;1202 t.state = TokenizeStateStart;
1197 continue;1203 continue;
1198 }1204 }
1199 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||1205 BigInt digit_value_bi;
1200 bignum_multiply_by_scalar(&t.cur_tok->data.num_lit.bignum, t.radix);1206 bigint_init_unsigned(&digit_value_bi, digit_value);
1201 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||1207
1202 bignum_increment_by_scalar(&t.cur_tok->data.num_lit.bignum, digit_value);1208 BigInt radix_bi;
1209 bigint_init_unsigned(&radix_bi, t.radix);
1210
1211 BigInt multiplied;
1212 bigint_mul(&multiplied, &t.cur_tok->data.int_lit.bigint, &radix_bi);
1213
1214 bigint_add(&t.cur_tok->data.int_lit.bigint, &multiplied, &digit_value_bi);
1203 break;1215 break;
1204 }1216 }
1205 case TokenizeStateNumberDot:1217 case TokenizeStateNumberDot:
1206 if (c == '.') {1218 {
1207 t.pos -= 2;1219 if (c == '.') {
1208 end_token(&t);1220 t.pos -= 2;
1209 t.state = TokenizeStateStart;1221 end_token(&t);
1222 t.state = TokenizeStateStart;
1223 continue;
1224 }
1225 t.pos -= 1;
1226 t.state = TokenizeStateFloatFraction;
1227 assert(t.cur_tok->id == TokenIdIntLiteral);
1228 bigint_init_bigint(&t.significand, &t.cur_tok->data.int_lit.bigint);
1229 set_token_id(&t, t.cur_tok, TokenIdFloatLiteral);
1210 continue;1230 continue;
1211 }1231 }
1212 t.pos -= 1;
1213 t.state = TokenizeStateFloatFraction;
1214 t.is_num_lit_float = true;
1215 continue;
1216 case TokenizeStateFloatFraction:1232 case TokenizeStateFloatFraction:
1217 {1233 {
1218 if (is_exponent_signifier(c, t.radix)) {1234 if (is_exponent_signifier(c, t.radix)) {
...@@ -1236,10 +1252,16 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1236,10 +1252,16 @@ void tokenize(Buf *buf, Tokenization *out) {
1236 // end of the token.1252 // end of the token.
1237 break;1253 break;
1238 }1254 }
1239 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||1255 BigInt digit_value_bi;
1240 bignum_multiply_by_scalar(&t.cur_tok->data.num_lit.bignum, t.radix);1256 bigint_init_unsigned(&digit_value_bi, digit_value);
1241 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||1257
1242 bignum_increment_by_scalar(&t.cur_tok->data.num_lit.bignum, digit_value);1258 BigInt radix_bi;
1259 bigint_init_unsigned(&radix_bi, t.radix);
1260
1261 BigInt multiplied;
1262 bigint_mul(&multiplied, &t.significand, &radix_bi);
1263
1264 bigint_add(&t.significand, &multiplied, &digit_value_bi);
1243 break;1265 break;
1244 }1266 }
1245 case TokenizeStateFloatExponentUnsigned:1267 case TokenizeStateFloatExponentUnsigned:
...@@ -1278,10 +1300,16 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1278,10 +1300,16 @@ void tokenize(Buf *buf, Tokenization *out) {
1278 // end of the token.1300 // end of the token.
1279 break;1301 break;
1280 }1302 }
1281 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||1303 BigInt digit_value_bi;
1282 bignum_multiply_by_scalar(&t.specified_exponent, 10);1304 bigint_init_unsigned(&digit_value_bi, digit_value);
1283 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||1305
1284 bignum_increment_by_scalar(&t.specified_exponent, digit_value);1306 BigInt radix_bi;
1307 bigint_init_unsigned(&radix_bi, 10);
1308
1309 BigInt multiplied;
1310 bigint_mul(&multiplied, &t.specified_exponent, &radix_bi);
1311
1312 bigint_add(&t.specified_exponent, &multiplied, &digit_value_bi);
1285 }1313 }
1286 break;1314 break;
1287 case TokenizeStateSawDash:1315 case TokenizeStateSawDash:
...@@ -1441,11 +1469,13 @@ const char * token_name(TokenId id) {...@@ -1441,11 +1469,13 @@ const char * token_name(TokenId id) {
1441 case TokenIdDivEq: return "/=";1469 case TokenIdDivEq: return "/=";
1442 case TokenIdDot: return ".";1470 case TokenIdDot: return ".";
1443 case TokenIdDoubleQuestion: return "??";1471 case TokenIdDoubleQuestion: return "??";
1444 case TokenIdEllipsis3: return "...";
1445 case TokenIdEllipsis2: return "..";1472 case TokenIdEllipsis2: return "..";
1473 case TokenIdEllipsis3: return "...";
1446 case TokenIdEof: return "EOF";1474 case TokenIdEof: return "EOF";
1447 case TokenIdEq: return "=";1475 case TokenIdEq: return "=";
1448 case TokenIdFatArrow: return "=>";1476 case TokenIdFatArrow: return "=>";
1477 case TokenIdFloatLiteral: return "FloatLiteral";
1478 case TokenIdIntLiteral: return "IntLiteral";
1449 case TokenIdKeywordAnd: return "and";1479 case TokenIdKeywordAnd: return "and";
1450 case TokenIdKeywordAsm: return "asm";1480 case TokenIdKeywordAsm: return "asm";
1451 case TokenIdKeywordBreak: return "break";1481 case TokenIdKeywordBreak: return "break";
...@@ -1494,7 +1524,6 @@ const char * token_name(TokenId id) {...@@ -1494,7 +1524,6 @@ const char * token_name(TokenId id) {
1494 case TokenIdMinusPercent: return "-%";1524 case TokenIdMinusPercent: return "-%";
1495 case TokenIdMinusPercentEq: return "-%=";1525 case TokenIdMinusPercentEq: return "-%=";
1496 case TokenIdModEq: return "%=";1526 case TokenIdModEq: return "%=";
1497 case TokenIdNumberLiteral: return "NumberLiteral";
1498 case TokenIdNumberSign: return "#";1527 case TokenIdNumberSign: return "#";
1499 case TokenIdPercent: return "%";1528 case TokenIdPercent: return "%";
1500 case TokenIdPercentDot: return "%.";1529 case TokenIdPercentDot: return "%.";
src/tokenizer.hpp+18-9
...@@ -9,7 +9,8 @@...@@ -9,7 +9,8 @@
9#define ZIG_TOKENIZER_HPP9#define ZIG_TOKENIZER_HPP
1010
11#include "buffer.hpp"11#include "buffer.hpp"
12#include "bignum.hpp"12#include "bigint.hpp"
13#include "bigfloat.hpp"
1314
14enum TokenId {15enum TokenId {
15 TokenIdAmpersand,16 TokenIdAmpersand,
...@@ -40,11 +41,13 @@ enum TokenId {...@@ -40,11 +41,13 @@ enum TokenId {
40 TokenIdDivEq,41 TokenIdDivEq,
41 TokenIdDot,42 TokenIdDot,
42 TokenIdDoubleQuestion,43 TokenIdDoubleQuestion,
43 TokenIdEllipsis3,
44 TokenIdEllipsis2,44 TokenIdEllipsis2,
45 TokenIdEllipsis3,
45 TokenIdEof,46 TokenIdEof,
46 TokenIdEq,47 TokenIdEq,
47 TokenIdFatArrow,48 TokenIdFatArrow,
49 TokenIdFloatLiteral,
50 TokenIdIntLiteral,
48 TokenIdKeywordAnd,51 TokenIdKeywordAnd,
49 TokenIdKeywordAsm,52 TokenIdKeywordAsm,
50 TokenIdKeywordBreak,53 TokenIdKeywordBreak,
...@@ -93,7 +96,6 @@ enum TokenId {...@@ -93,7 +96,6 @@ enum TokenId {
93 TokenIdMinusPercent,96 TokenIdMinusPercent,
94 TokenIdMinusPercentEq,97 TokenIdMinusPercentEq,
95 TokenIdModEq,98 TokenIdModEq,
96 TokenIdNumberLiteral,
97 TokenIdNumberSign,99 TokenIdNumberSign,
98 TokenIdPercent,100 TokenIdPercent,
99 TokenIdPercentDot,101 TokenIdPercentDot,
...@@ -118,13 +120,17 @@ enum TokenId {...@@ -118,13 +120,17 @@ enum TokenId {
118 TokenIdTimesPercentEq,120 TokenIdTimesPercentEq,
119};121};
120122
121struct TokenNumLit {123struct TokenFloatLit {
122 BigNum bignum;124 BigFloat bigfloat;
123 // overflow is true if when parsing the number, we discovered it would not125 // overflow is true if when parsing the number, we discovered it would not fit
124 // fit without losing data in a uint64_t or double126 // without losing data
125 bool overflow;127 bool overflow;
126};128};
127129
130struct TokenIntLit {
131 BigInt bigint;
132};
133
128struct TokenStrLit {134struct TokenStrLit {
129 Buf str;135 Buf str;
130 bool is_c_str;136 bool is_c_str;
...@@ -142,8 +148,11 @@ struct Token {...@@ -142,8 +148,11 @@ struct Token {
142 size_t start_column;148 size_t start_column;
143149
144 union {150 union {
145 // TokenIdNumberLiteral151 // TokenIdIntLiteral
146 TokenNumLit num_lit;152 TokenIntLit int_lit;
153
154 // TokenIdFloatLiteral
155 TokenFloatLit float_lit;
147156
148 // TokenIdStringLiteral or TokenIdSymbol157 // TokenIdStringLiteral or TokenIdSymbol
149 TokenStrLit str_lit;158 TokenStrLit str_lit;
std/math/fabs.zig+2-2
...@@ -36,8 +36,8 @@ test "math.fabs" {...@@ -36,8 +36,8 @@ test "math.fabs" {
36}36}
3737
38test "math.fabs32" {38test "math.fabs32" {
39 assert(fabs64(1.0) == 1.0);39 assert(fabs32(1.0) == 1.0);
40 assert(fabs64(-1.0) == 1.0);40 assert(fabs32(-1.0) == 1.0);
41}41}
4242
43test "math.fabs64" {43test "math.fabs64" {
std/math/log10.zig+1-1
...@@ -139,7 +139,7 @@ fn log10_64(x_: f64) -> f64 {...@@ -139,7 +139,7 @@ fn log10_64(x_: f64) -> f64 {
139 // hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f)139 // hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f)
140 var hi = f - hfsq;140 var hi = f - hfsq;
141 var hii = @bitCast(u64, hi);141 var hii = @bitCast(u64, hi);
142 hii &= @maxValue(u64) << 32;142 hii &= u64(@maxValue(u64)) <<% 32;
143 hi = @bitCast(f64, hii);143 hi = @bitCast(f64, hii);
144 const lo = f - hi - hfsq + s * (hfsq + R);144 const lo = f - hi - hfsq + s * (hfsq + R);
145145
std/math/log2.zig+1-1
...@@ -133,7 +133,7 @@ fn log2_64(x_: f64) -> f64 {...@@ -133,7 +133,7 @@ fn log2_64(x_: f64) -> f64 {
133 // hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f)133 // hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f)
134 var hi = f - hfsq;134 var hi = f - hfsq;
135 var hii = @bitCast(u64, hi);135 var hii = @bitCast(u64, hi);
136 hii &= @maxValue(u64) << 32;136 hii &= u64(@maxValue(u64)) <<% 32;
137 hi = @bitCast(f64, hii);137 hi = @bitCast(f64, hii);
138 const lo = f - hi - hfsq + s * (hfsq + R);138 const lo = f - hi - hfsq + s * (hfsq + R);
139139
test/cases/math.zig+28-6
...@@ -58,15 +58,33 @@ test "@shlWithOverflow" {...@@ -58,15 +58,33 @@ test "@shlWithOverflow" {
58}58}
5959
60test "@clz" {60test "@clz" {
61 assert(@clz(u8(0b00001010)) == 4);61 testClz();
62 assert(@clz(u8(0b10001010)) == 0);62 comptime testClz();
63 assert(@clz(u8(0b00000000)) == 8);63}
64
65fn testClz() {
66 assert(clz(u8(0b00001010)) == 4);
67 assert(clz(u8(0b10001010)) == 0);
68 assert(clz(u8(0b00000000)) == 8);
69}
70
71fn clz(x: var) -> usize {
72 @clz(x)
64}73}
6574
66test "@ctz" {75test "@ctz" {
67 assert(@ctz(u8(0b10100000)) == 5);76 testCtz();
68 assert(@ctz(u8(0b10001010)) == 1);77 comptime testCtz();
69 assert(@ctz(u8(0b00000000)) == 8);78}
79
80fn testCtz() {
81 assert(ctz(u8(0b10100000)) == 5);
82 assert(ctz(u8(0b10001010)) == 1);
83 assert(ctz(u8(0b00000000)) == 8);
84}
85
86fn ctz(x: var) -> usize {
87 @ctz(x)
70}88}
7189
72test "assignment operators" {90test "assignment operators" {
...@@ -229,3 +247,7 @@ test "allow signed integer division/remainder when values are comptime known and...@@ -229,3 +247,7 @@ test "allow signed integer division/remainder when values are comptime known and
229 assert(5 % 3 == 2);247 assert(5 % 3 == 2);
230 assert(-6 % 3 == 0);248 assert(-6 % 3 == 0);
231}249}
250
251test "float literal parsing" {
252 comptime assert(0x1.0 == 1.0);
253}