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/
77/.cproject
88/.project
99/.settings/
10build-llvm-debug/
CMakeLists.txt+2-1
......@@ -44,7 +44,8 @@ include_directories(
4444set(ZIG_SOURCES
4545 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"
4646 "${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"
4849 "${CMAKE_SOURCE_DIR}/src/buffer.cpp"
4950 "${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp"
5051 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
doc/langref.md+1-1
......@@ -143,7 +143,7 @@ StructLiteralField = "." Symbol "=" Expression
143143
144144PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%"
145145
146PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
146PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
147147
148148ArrayType = "[" option(Expression) "]" option("const") TypeExpr
149149
src/all_types.hpp+20-7
......@@ -13,7 +13,8 @@
1313#include "zig_llvm.hpp"
1414#include "hash_map.hpp"
1515#include "errmsg.hpp"
16#include "bignum.hpp"
16#include "bigint.hpp"
17#include "bigfloat.hpp"
1718#include "target.hpp"
1819
1920struct AstNode;
......@@ -215,6 +216,11 @@ struct ConstGlobalRefs {
215216 LLVMValueRef llvm_global;
216217};
217218
219enum ConstNumLitKind {
220 ConstNumLitKindInt,
221 ConstNumLitKindFloat,
222};
223
218224struct ConstExprValue {
219225 TypeTableEntry *type;
220226 ConstValSpecial special;
......@@ -222,7 +228,8 @@ struct ConstExprValue {
222228
223229 union {
224230 // populated if special == ConstValSpecialStatic
225 BigNum x_bignum;
231 BigInt x_bigint;
232 BigFloat x_bigfloat;
226233 bool x_bool;
227234 ConstFn x_fn;
228235 ConstBoundFnValue x_bound_fn;
......@@ -347,7 +354,8 @@ enum NodeType {
347354 NodeTypeTestDecl,
348355 NodeTypeBinOpExpr,
349356 NodeTypeUnwrapErrorExpr,
350 NodeTypeNumberLiteral,
357 NodeTypeFloatLiteral,
358 NodeTypeIntLiteral,
351359 NodeTypeStringLiteral,
352360 NodeTypeCharLiteral,
353361 NodeTypeSymbol,
......@@ -748,14 +756,18 @@ struct AstNodeCharLiteral {
748756 uint8_t value;
749757};
750758
751struct AstNodeNumberLiteral {
752 BigNum *bignum;
759struct AstNodeFloatLiteral {
760 BigFloat *bigfloat;
753761
754762 // overflow is true if when parsing the number, we discovered it would not
755 // fit without losing data in a uint64_t or double
763 // fit without losing data in a double
756764 bool overflow;
757765};
758766
767struct AstNodeIntLiteral {
768 BigInt *bigint;
769};
770
759771struct AstNodeStructValueField {
760772 Buf *name;
761773 AstNode *expr;
......@@ -854,7 +866,8 @@ struct AstNode {
854866 AstNodeStructField struct_field;
855867 AstNodeStringLiteral string_literal;
856868 AstNodeCharLiteral char_literal;
857 AstNodeNumberLiteral number_literal;
869 AstNodeFloatLiteral float_literal;
870 AstNodeIntLiteral int_literal;
858871 AstNodeContainerInitExpr container_init_expr;
859872 AstNodeStructValueField struct_val_field;
860873 AstNodeNullLiteral null_literal;
src/analyze.cpp+58-76
......@@ -2194,7 +2194,8 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
21942194 case NodeTypeFnCallExpr:
21952195 case NodeTypeArrayAccessExpr:
21962196 case NodeTypeSliceExpr:
2197 case NodeTypeNumberLiteral:
2197 case NodeTypeFloatLiteral:
2198 case NodeTypeIntLiteral:
21982199 case NodeTypeStringLiteral:
21992200 case NodeTypeCharLiteral:
22002201 case NodeTypeBoolLiteral:
......@@ -3247,10 +3248,17 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
32473248 case TypeTableEntryIdInt:
32483249 case TypeTableEntryIdNumLitInt:
32493250 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 }
32513259 case TypeTableEntryIdFloat:
32523260 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);
32543262 case TypeTableEntryIdArgTuple:
32553263 return (uint32_t)const_val->data.x_arg_tuple.start_index * (uint32_t)281907309 +
32563264 (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) {
34733481 ConstExprValue *this_char = &const_val->data.x_array.s_none.elements[i];
34743482 this_char->special = ConstValSpecialStatic;
34753483 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]);
34773485 }
34783486}
34793487
......@@ -3494,12 +3502,12 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
34943502 ConstExprValue *this_char = &array_val->data.x_array.s_none.elements[i];
34953503 this_char->special = ConstValSpecialStatic;
34963504 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]);
34983506 }
34993507 ConstExprValue *null_char = &array_val->data.x_array.s_none.elements[len_with_null - 1];
35003508 null_char->special = ConstValSpecialStatic;
35013509 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
35043512 // then make the pointer point to it
35053513 const_val->special = ConstValSpecialStatic;
......@@ -3518,8 +3526,8 @@ ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {
35183526void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative) {
35193527 const_val->special = ConstValSpecialStatic;
35203528 const_val->type = type;
3521 bignum_init_unsigned(&const_val->data.x_bignum, x);
3522 const_val->data.x_bignum.is_negative = negative;
3529 bigint_init_unsigned(&const_val->data.x_bigint, x);
3530 const_val->data.x_bigint.is_negative = negative;
35233531}
35243532
35253533ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative) {
......@@ -3539,7 +3547,7 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x) {
35393547void init_const_signed(ConstExprValue *const_val, TypeTableEntry *type, int64_t x) {
35403548 const_val->special = ConstValSpecialStatic;
35413549 const_val->type = type;
3542 bignum_init_signed(&const_val->data.x_bignum, x);
3550 bigint_init_signed(&const_val->data.x_bigint, x);
35433551}
35443552
35453553ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x) {
......@@ -3551,7 +3559,7 @@ ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x) {
35513559void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value) {
35523560 const_val->special = ConstValSpecialStatic;
35533561 const_val->type = type;
3554 bignum_init_float(&const_val->data.x_bignum, value);
3562 bigfloat_init_float(&const_val->data.x_bigfloat, value);
35553563}
35563564
35573565ConstExprValue *create_const_float(TypeTableEntry *type, double value) {
......@@ -3788,12 +3796,13 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
37883796 return a->data.x_fn.fn_entry == b->data.x_fn.fn_entry;
37893797 case TypeTableEntryIdBool:
37903798 return a->data.x_bool == b->data.x_bool;
3791 case TypeTableEntryIdInt:
37923799 case TypeTableEntryIdFloat:
37933800 case TypeTableEntryIdNumLitFloat:
3801 return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ;
3802 case TypeTableEntryIdInt:
37943803 case TypeTableEntryIdNumLitInt:
37953804 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;
37973806 case TypeTableEntryIdPointer:
37983807 if (a->data.x_ptr.special != b->data.x_ptr.special)
37993808 return false;
......@@ -3876,58 +3885,47 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
38763885 zig_unreachable();
38773886}
38783887
3879uint64_t max_unsigned_val(TypeTableEntry *type_entry) {
3880 assert(type_entry->id == TypeTableEntryIdInt);
3881 if (type_entry->data.integral.bit_count == 64) {
3882 return UINT64_MAX;
3883 } else {
3884 return (((uint64_t)1) << type_entry->data.integral.bit_count) - 1;
3888void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max) {
3889 assert(int_type->id == TypeTableEntryIdInt);
3890 if (int_type->data.integral.bit_count == 0) {
3891 bigint_init_unsigned(bigint, 0);
3892 return;
38853893 }
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) {
3889 assert(type_entry->id == TypeTableEntryIdInt);
3900 size_t shift_amt = int_type->data.integral.bit_count - (int_type->data.integral.is_signed ? 1 : 0);
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) {
3892 return INT64_MAX;
3893 } else {
3894 return (((uint64_t)1) << (type_entry->data.integral.bit_count - 1)) - 1;
3895 }
3896}
3904 BigInt shifted_bi = {0};
3905 bigint_shl(&shifted_bi, &one, &bit_count_bi);
38973906
3898int64_t min_signed_val(TypeTableEntry *type_entry) {
3899 assert(type_entry->id == TypeTableEntryIdInt);
3900 if (type_entry->data.integral.bit_count == 64) {
3901 return INT64_MIN;
3902 } else {
3903 return -((int64_t)(((uint64_t)1) << (type_entry->data.integral.bit_count - 1)));
3904 }
3905}
3907 bigint_sub(bigint, &shifted_bi, &one);
3908 } else if (int_type->data.integral.is_signed) {
3909 // - (1 << (bit_count - 1))
3910 BigInt one = {0};
3911 bigint_init_unsigned(&one, 1);
39063912
3907void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigNum *bignum, bool is_max) {
3908 assert(int_type->id == TypeTableEntryIdInt);
3909 if (is_max) {
3910 if (int_type->data.integral.is_signed) {
3911 int64_t val = max_signed_val(int_type);
3912 bignum_init_signed(bignum, val);
3913 } else {
3914 uint64_t val = max_unsigned_val(int_type);
3915 bignum_init_unsigned(bignum, val);
3916 }
3913 BigInt bit_count_bi = {0};
3914 bigint_init_unsigned(&bit_count_bi, int_type->data.integral.bit_count - 1);
3915
3916 BigInt shifted_bi = {0};
3917 bigint_shl(&shifted_bi, &one, &bit_count_bi);
3918
3919 bigint_negate(bigint, &shifted_bi);
39173920 } else {
3918 if (int_type->data.integral.is_signed) {
3919 int64_t val = min_signed_val(int_type);
3920 bignum_init_signed(bignum, val);
3921 } else {
3922 bignum_init_unsigned(bignum, 0);
3923 }
3921 bigint_init_unsigned(bigint, 0);
39243922 }
39253923}
39263924
39273925void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) {
39283926 if (type_entry->id == TypeTableEntryIdInt) {
39293927 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);
39313929 } else if (type_entry->id == TypeTableEntryIdFloat) {
39323930 zig_panic("TODO analyze_min_max_value float");
39333931 } else if (type_entry->id == TypeTableEntryIdBool) {
......@@ -3967,32 +3965,15 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
39673965 buf_appendf(buf, "{}");
39683966 return;
39693967 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);
39713970 return;
39723971 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;
39823972 case TypeTableEntryIdInt:
3983 {
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 }
3973 bigint_write_buf(buf, &const_val->data.x_bigint, 10);
39893974 return;
3990 case TypeTableEntryIdFloat:
3991 {
3992 BigNum *bignum = &const_val->data.x_bignum;
3993 assert(bignum->kind == BigNumKindFloat);
3994 buf_appendf(buf, "%f", bignum->data.x_float);
3995 }
3975 case TypeTableEntryIdMetaType:
3976 buf_appendf(buf, "%s", buf_ptr(&const_val->data.x_type->name));
39963977 return;
39973978 case TypeTableEntryIdUnreachable:
39983979 buf_appendf(buf, "@unreachable()");
......@@ -4060,7 +4041,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
40604041 buf_append_char(buf, '"');
40614042 for (uint64_t i = 0; i < len; i += 1) {
40624043 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);
40644045 assert(big_c <= UINT8_MAX);
40654046 uint8_t c = (uint8_t)big_c;
40664047 if (c == '"') {
......@@ -4146,7 +4127,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
41464127 case TypeTableEntryIdEnumTag:
41474128 {
41484129 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];
41504132 buf_appendf(buf, "%s.%s", buf_ptr(&enum_type->name), buf_ptr(field->name));
41514133 return;
41524134 }
src/analyze.hpp+1-3
......@@ -84,9 +84,7 @@ void complete_enum(CodeGen *g, TypeTableEntry *enum_type);
8484bool ir_get_var_is_comptime(VariableTableEntry *var);
8585bool const_values_equal(ConstExprValue *a, ConstExprValue *b);
8686void 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);
88int64_t min_signed_val(TypeTableEntry *type_entry);
89uint64_t max_unsigned_val(TypeTableEntry *type_entry);
87void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max);
9088
9189void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);
9290void 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) {
182182 return "ErrorValueDecl";
183183 case NodeTypeTestDecl:
184184 return "TestDecl";
185 case NodeTypeNumberLiteral:
186 return "NumberLiteral";
185 case NodeTypeIntLiteral:
186 return "IntLiteral";
187 case NodeTypeFloatLiteral:
188 return "FloatLiteral";
187189 case NodeTypeStringLiteral:
188190 return "StringLiteral";
189191 case NodeTypeCharLiteral:
......@@ -536,17 +538,20 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
536538 render_node_ungrouped(ar, node->data.bin_op_expr.op2);
537539 if (!grouped) fprintf(ar->f, ")");
538540 break;
539 case NodeTypeNumberLiteral:
540 switch (node->data.number_literal.bignum->kind) {
541 case BigNumKindInt:
542 {
543 const char *negative_str = node->data.number_literal.bignum->is_negative ? "-" : "";
544 fprintf(ar->f, "%s%" ZIG_PRI_llu, negative_str, node->data.number_literal.bignum->data.x_uint);
545 }
546 break;
547 case BigNumKindFloat:
548 fprintf(ar->f, "%f", node->data.number_literal.bignum->data.x_float);
549 break;
541 case NodeTypeFloatLiteral:
542 {
543 Buf rendered_buf = BUF_INIT;
544 buf_resize(&rendered_buf, 0);
545 bigfloat_write_buf(&rendered_buf, node->data.float_literal.bigfloat);
546 fprintf(ar->f, "%s", buf_ptr(&rendered_buf));
547 }
548 break;
549 case NodeTypeIntLiteral:
550 {
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));
550555 }
551556 break;
552557 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 {
12031203 DivKindExact,
12041204};
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
12061223static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_math,
12071224 LLVMValueRef val1, LLVMValueRef val2,
12081225 TypeTableEntry *type_entry, DivKind div_kind)
......@@ -1230,7 +1247,9 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_m
12301247
12311248 if (type_entry->id == TypeTableEntryIdInt && type_entry->data.integral.is_signed) {
12321249 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);
12341253 LLVMBasicBlockRef overflow_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowOk");
12351254 LLVMBasicBlockRef overflow_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowFail");
12361255 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
17651784 LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);
17661785 LLVMValueRef neq_zero_bit = LLVMBuildICmp(g->builder, LLVMIntNE, target_val, zero, "");
17671786 LLVMValueRef ok_bit;
1768 uint64_t biggest_possible_err_val = max_unsigned_val(actual_type);
1769 if (biggest_possible_err_val < g->error_decls.length) {
1787
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 {
17701794 ok_bit = neq_zero_bit;
17711795 } else {
17721796 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
33173341 LLVMValueRef int_val = gen_const_val(g, const_val);
33183342 return LLVMConstZExt(int_val, big_int_type_ref);
33193343 }
3320 return LLVMConstInt(big_int_type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
33213344 case TypeTableEntryIdFloat:
33223345 {
33233346 LLVMValueRef float_val = gen_const_val(g, const_val);
......@@ -3374,21 +3397,13 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
33743397 switch (type_entry->id) {
33753398 case TypeTableEntryIdInt:
33763399 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);
33783401 case TypeTableEntryIdPureError:
33793402 assert(const_val->data.x_pure_err);
33803403 return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref,
33813404 const_val->data.x_pure_err->value, false);
33823405 case TypeTableEntryIdFloat:
3383 if (const_val->data.x_bignum.kind == BigNumKindFloat) {
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 }
3406 return bigfloat_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigfloat);
33923407 case TypeTableEntryIdBool:
33933408 if (const_val->data.x_bool) {
33943409 return LLVMConstAllOnes(LLVMInt1Type());
......@@ -3866,7 +3881,7 @@ static void do_code_gen(CodeGen *g) {
38663881 ConstExprValue *const_val = var->value;
38673882 assert(const_val->special != ConstValSpecialRuntime);
38683883 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);
38703885 gen_global_var(g, var, init_val, var_type);
38713886 continue;
38723887 }
......@@ -3875,10 +3890,9 @@ static void do_code_gen(CodeGen *g) {
38753890 // Generate debug info for it but that's it.
38763891 ConstExprValue *const_val = var->value;
38773892 assert(const_val->special != ConstValSpecialRuntime);
3878 TypeTableEntry *var_type = const_val->data.x_bignum.is_negative ?
3879 g->builtin_types.entry_isize : g->builtin_types.entry_usize;
3880 LLVMValueRef init_val = LLVMConstInt(var_type->type_ref,
3881 bignum_to_twos_complement(&const_val->data.x_bignum), false);
3893 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
3894 TypeTableEntry *var_type = get_int_type(g, const_val->data.x_bigint.is_negative, bits_needed);
3895 LLVMValueRef init_val = bigint_to_llvm_const(var_type->type_ref, &const_val->data.x_bigint);
38823896 gen_global_var(g, var, init_val, var_type);
38833897 continue;
38843898 }
src/ir.cpp+405-300
......@@ -656,16 +656,23 @@ static IrInstruction *ir_build_const_uint(IrBuilder *irb, Scope *scope, AstNode
656656 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
657657 const_instruction->base.value.type = irb->codegen->builtin_types.entry_num_lit_int;
658658 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);
660660 return &const_instruction->base;
661661}
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) {
664664 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
665 const_instruction->base.value.type = (bignum->kind == BigNumKindInt) ?
666 irb->codegen->builtin_types.entry_num_lit_int : irb->codegen->builtin_types.entry_num_lit_float;
665 const_instruction->base.value.type = irb->codegen->builtin_types.entry_num_lit_int;
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;
667674 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);
669676 return &const_instruction->base;
670677}
671678
......@@ -680,7 +687,7 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, Scope *scope, AstNode
680687 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
681688 const_instruction->base.value.type = irb->codegen->builtin_types.entry_usize;
682689 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);
684691 return &const_instruction->base;
685692}
686693
......@@ -3687,15 +3694,21 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)
36873694 zig_unreachable();
36883695}
36893696
3690static IrInstruction *ir_gen_num_lit(IrBuilder *irb, Scope *scope, AstNode *node) {
3691 assert(node->type == NodeTypeNumberLiteral);
3697static IrInstruction *ir_gen_int_lit(IrBuilder *irb, Scope *scope, AstNode *node) {
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) {
3694 add_node_error(irb->codegen, node, buf_sprintf("number literal too large to be represented in any type"));
3703static IrInstruction *ir_gen_float_lit(IrBuilder *irb, Scope *scope, AstNode *node) {
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"));
36953708 return irb->codegen->invalid_instruction;
36963709 }
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);
36993712}
37003713
37013714static 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
59335946 return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval);
59345947 case NodeTypeBinOpExpr:
59355948 return ir_lval_wrap(irb, scope, ir_gen_bin_op(irb, scope, node), lval);
5936 case NodeTypeNumberLiteral:
5937 return ir_lval_wrap(irb, scope, ir_gen_num_lit(irb, scope, node), lval);
5949 case NodeTypeIntLiteral:
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);
59385953 case NodeTypeCharLiteral:
59395954 return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval);
59405955 case NodeTypeSymbol:
......@@ -6184,6 +6199,13 @@ static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *so
61846199 return true;
61856200}
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
61876209static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) {
61886210 if (type_is_invalid(other_type)) {
61896211 return false;
......@@ -6191,44 +6213,51 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
61916213
61926214 ConstExprValue *const_val = &instruction->value;
61936215 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);
61946221 if (other_type->id == TypeTableEntryIdFloat) {
61956222 return true;
6196 } else if (other_type->id == TypeTableEntryIdInt &&
6197 const_val->data.x_bignum.kind == BigNumKindInt)
6198 {
6199 if (bignum_fits_in_bits(&const_val->data.x_bignum, other_type->data.integral.bit_count,
6223 } else if (other_type->id == TypeTableEntryIdInt && const_val_is_int) {
6224 if (bigint_fits_in_bits(&const_val->data.x_bigint, other_type->data.integral.bit_count,
62006225 other_type->data.integral.is_signed))
62016226 {
62026227 return true;
62036228 }
6204 } else if ((other_type->id == TypeTableEntryIdNumLitFloat && const_val->data.x_bignum.kind == BigNumKindFloat) ||
6205 (other_type->id == TypeTableEntryIdNumLitInt && const_val->data.x_bignum.kind == BigNumKindInt ))
6206 {
6229 } else if (const_val_fits_in_num_lit(const_val, other_type)) {
62076230 return true;
62086231 } else if (other_type->id == TypeTableEntryIdMaybe) {
62096232 TypeTableEntry *child_type = other_type->data.maybe.child_type;
6210 if ((child_type->id == TypeTableEntryIdNumLitFloat && const_val->data.x_bignum.kind == BigNumKindFloat) ||
6211 (child_type->id == TypeTableEntryIdNumLitInt && const_val->data.x_bignum.kind == BigNumKindInt ))
6212 {
6233 if (const_val_fits_in_num_lit(const_val, child_type)) {
62136234 return true;
6214 } else if (child_type->id == TypeTableEntryIdInt && const_val->data.x_bignum.kind == BigNumKindInt) {
6215 if (bignum_fits_in_bits(&const_val->data.x_bignum,
6235 } else if (child_type->id == TypeTableEntryIdInt && const_val_is_int) {
6236 if (bigint_fits_in_bits(&const_val->data.x_bigint,
62166237 child_type->data.integral.bit_count,
62176238 child_type->data.integral.is_signed))
62186239 {
62196240 return true;
62206241 }
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) {
62226243 return true;
62236244 }
62246245 }
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
62286257 ir_add_error(ira, instruction,
62296258 buf_sprintf("%s value %s cannot be implicitly casted to type '%s'",
62306259 num_lit_str,
6231 buf_ptr(bignum_to_buf(&const_val->data.x_bignum)),
6260 buf_ptr(val_buf),
62326261 buf_ptr(&other_type->name)));
62336262 return false;
62346263}
......@@ -6643,7 +6672,13 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
66436672 break;
66446673 }
66456674 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 }
66476682 const_val->type = new_type;
66486683 break;
66496684 case CastOpResizeSlice:
......@@ -6651,15 +6686,15 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
66516686 // can't do it
66526687 break;
66536688 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);
66556690 const_val->special = ConstValSpecialStatic;
66566691 break;
66576692 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);
66596694 const_val->special = ConstValSpecialStatic;
66606695 break;
66616696 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);
66636698 const_val->special = ConstValSpecialStatic;
66646699 break;
66656700 }
......@@ -6878,7 +6913,7 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr
68786913
68796914static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value) {
68806915 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);
68826917 return ira->codegen->builtin_types.entry_usize;
68836918}
68846919
......@@ -7239,12 +7274,12 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
72397274 if (!val)
72407275 return ira->codegen->invalid_instruction;
72417276 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) {
72437278 ir_add_error(ira, source_instr,
72447279 buf_sprintf("attempt to cast negative value to unsigned integer"));
72457280 return ira->codegen->invalid_instruction;
72467281 }
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,
72487283 wanted_type->data.integral.is_signed))
72497284 {
72507285 ir_add_error(ira, source_instr,
......@@ -7255,7 +7290,11 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
72557290 }
72567291 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
72577292 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 }
72597298 result->value.type = wanted_type;
72607299 return result;
72617300 }
......@@ -7278,7 +7317,7 @@ static IrInstruction *ir_analyze_ptr_to_int(IrAnalyze *ira, IrInstruction *sourc
72787317 if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
72797318 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
72807319 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);
72827321 return result;
72837322 }
72847323 }
......@@ -7299,9 +7338,20 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
72997338 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
73007339 if (!val)
73017340 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
73027352 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
73037353 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);
73057355 return result;
73067356 }
73077357
......@@ -7320,7 +7370,13 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction
73207370
73217371 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
73227372 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 }
73247380 return result;
73257381}
73267382
......@@ -7336,13 +7392,17 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
73367392 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
73377393 source_instr->source_node, ira->codegen->builtin_types.entry_pure_error);
73387394
7339 uint64_t index = val->data.x_bignum.data.x_uint;
7340 if (index == 0 || index >= ira->codegen->error_decls.length) {
7395 BigInt err_count;
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);
73417400 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)));
73437402 return ira->codegen->invalid_instruction;
73447403 }
73457404
7405 size_t index = bigint_as_unsigned(&val->data.x_bigint);
73467406 AstNode *error_decl_node = ira->codegen->error_decls.at(index);
73477407 result->value.data.x_pure_err = error_decl_node->data.error_value_decl.err;
73487408 return result;
......@@ -7378,9 +7438,9 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
73787438 }
73797439 result->value.type = wanted_type;
73807440 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,
73847444 wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed))
73857445 {
73867446 ir_add_error_node(ira, source_instr->source_node,
......@@ -7392,9 +7452,9 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
73927452 return result;
73937453 }
73947454
7395 BigNum bn;
7396 bignum_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)) {
7455 BigInt bn;
7456 bigint_init_unsigned(&bn, ira->codegen->error_decls.length);
7457 if (!bigint_fits_in_bits(&bn, wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed)) {
73987458 ir_add_error_node(ira, source_instr->source_node,
73997459 buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name)));
74007460 return ira->codegen->invalid_instruction;
......@@ -7861,7 +7921,7 @@ static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out
78617921 if (!const_val)
78627922 return false;
78637923
7864 *out = const_val->data.x_bignum.data.x_uint;
7924 *out = bigint_as_unsigned(&const_val->data.x_bigint);
78657925 return true;
78667926}
78677927
......@@ -7941,7 +8001,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
79418001 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
79428002 ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
79438003 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);
79458005 Buf *result = buf_alloc();
79468006 buf_resize(result, len);
79478007 for (size_t i = 0; i < len; i += 1) {
......@@ -7951,7 +8011,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
79518011 ir_add_error(ira, casted_value, buf_sprintf("use of undefined value"));
79528012 return nullptr;
79538013 }
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);
79558015 assert(big_c <= UINT8_MAX);
79568016 uint8_t c = (uint8_t)big_c;
79578017 buf_ptr(result)[i] = c;
......@@ -8039,6 +8099,24 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
80398099 return bool_type;
80408100}
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
80428120static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
80438121 IrInstruction *op1 = bin_op_instruction->op1->other;
80448122 IrInstruction *op2 = bin_op_instruction->op2->other;
......@@ -8157,30 +8235,13 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
81578235 ConstExprValue *op1_val = &casted_op1->value;
81588236 ConstExprValue *op2_val = &casted_op2->value;
81598237 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);
81648238 bool answer;
8165 if (type_can_gt_lt_cmp) {
8166 bool (*bignum_cmp)(BigNum *, BigNum *);
8167 if (op_id == IrBinOpCmpEq) {
8168 bignum_cmp = bignum_cmp_eq;
8169 } else if (op_id == IrBinOpCmpNotEq) {
8170 bignum_cmp = bignum_cmp_neq;
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);
8239 if (resolved_type->id == TypeTableEntryIdNumLitFloat || resolved_type->id == TypeTableEntryIdFloat) {
8240 Cmp cmp_result = bigfloat_cmp(&op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
8241 answer = resolve_cmp_op_id(op_id, cmp_result);
8242 } else if (resolved_type->id == TypeTableEntryIdNumLitInt || resolved_type->id == TypeTableEntryIdInt) {
8243 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
8244 answer = resolve_cmp_op_id(op_id, cmp_result);
81848245 } else {
81858246 bool are_equal = resolved_type->id == TypeTableEntryIdVoid || const_values_equal(op1_val, op2_val);
81868247 if (op_id == IrBinOpCmpEq) {
......@@ -8220,7 +8281,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
82208281 } else {
82218282 known_left_val = nullptr;
82228283 }
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 &&
82248285 (flipped_op_id == IrBinOpCmpLessOrEq || flipped_op_id == IrBinOpCmpGreaterThan))
82258286 {
82268287 bool answer = (flipped_op_id == IrBinOpCmpLessOrEq);
......@@ -8236,101 +8297,35 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
82368297 return ira->codegen->builtin_types.entry_bool;
82378298}
82388299
8239enum EvalBigNumSpecial {
8240 EvalBigNumSpecialNone,
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)
8300static int ir_eval_math_op(TypeTableEntry *type_entry, ConstExprValue *op1_val,
8301 IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
82488302{
8249 bool is_int = false;
8250 bool is_float = false;
8251 if (type->id == TypeTableEntryIdInt ||
8252 type->id == TypeTableEntryIdNumLitInt)
8253 {
8303 bool is_int;
8304 bool is_float;
8305 Cmp op2_zcmp;
8306 if (type_entry->id == TypeTableEntryIdInt || type_entry->id == TypeTableEntryIdNumLitInt) {
82548307 is_int = true;
8255 } else if (type->id == TypeTableEntryIdFloat ||
8256 type->id == TypeTableEntryIdNumLitFloat)
8308 is_float = false;
8309 op2_zcmp = bigint_cmp_zero(&op2_val->data.x_bigint);
8310 } else if (type_entry->id == TypeTableEntryIdFloat ||
8311 type_entry->id == TypeTableEntryIdNumLitFloat)
82578312 {
8313 is_int = false;
82588314 is_float = true;
8315 op2_zcmp = bigfloat_cmp_zero(&op2_val->data.x_bigfloat);
82598316 } else {
82608317 zig_unreachable();
82618318 }
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,
8310 type->data.integral.bit_count, type->data.integral.is_signed))
8320 if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod ||
8321 op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ)
83118322 {
8312 if (special == EvalBigNumSpecialWrapping) {
8313 if (type->data.integral.is_signed) {
8314 out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1;
8315 out_val->data.x_bignum.is_negative = !out_val->data.x_bignum.is_negative;
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 }
8323 return ErrorDivByZero;
8324 }
8325 if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) {
8326 return ErrorNegativeDenominator;
83258327 }
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{
83348329 switch (op_id) {
83358330 case IrBinOpInvalid:
83368331 case IrBinOpBoolOr:
......@@ -8346,43 +8341,128 @@ static int ir_eval_math_op(TypeTableEntry *canon_type, ConstExprValue *op1_val,
83468341 case IrBinOpRemUnspecified:
83478342 zig_unreachable();
83488343 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;
83508347 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;
83528351 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;
83548355 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;
83568359 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;
83588364 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;
83608368 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;
83628375 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;
83648380 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;
83668387 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;
83688392 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;
83708399 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;
83728404 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;
83748408 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;
83768415 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;
83788422 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;
83808439 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;
83828446 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;
83848453 }
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;
83868466}
83878467
83888468static 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
83958475 IrBinOp op_id = bin_op_instruction->op_id;
83968476
83978477 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) ||
8399 resolved_type->id == TypeTableEntryIdFloat ||
8400 (resolved_type->id == TypeTableEntryIdNumLitFloat &&
8401 (op1->value.data.x_bignum.data.x_float < 0.0 || op2->value.data.x_bignum.data.x_float < 0.0)) ||
8402 (resolved_type->id == TypeTableEntryIdNumLitInt &&
8403 (op1->value.data.x_bignum.is_negative || op2->value.data.x_bignum.is_negative)));
8404 if (op_id == IrBinOpDivUnspecified) {
8405 if (is_int && is_signed) {
8478 bool is_float = resolved_type->id == TypeTableEntryIdFloat || resolved_type->id == TypeTableEntryIdNumLitFloat;
8479 bool is_signed_div = (
8480 (resolved_type->id == TypeTableEntryIdInt && resolved_type->data.integral.is_signed) ||
8481 resolved_type->id == TypeTableEntryIdFloat ||
8482 (resolved_type->id == TypeTableEntryIdNumLitFloat &&
8483 ((bigfloat_cmp_zero(&op1->value.data.x_bigfloat) != CmpGT) !=
8484 (bigfloat_cmp_zero(&op2->value.data.x_bigfloat) != CmpGT))) ||
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) {
84068491 bool ok = false;
84078492 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) {
84098494 // the division by zero error will be caught later, but we don't have a
84108495 // division function ambiguity problem.
84118496 op_id = IrBinOpDivTrunc;
84128497 ok = true;
84138498 } else {
8414 BigNum trunc_result;
8415 BigNum floor_result;
8416 if (bignum_div_trunc(&trunc_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8417 zig_unreachable();
8418 }
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)) {
8499 BigInt trunc_result;
8500 BigInt floor_result;
8501 bigint_div_trunc(&trunc_result, &op1->value.data.x_bigint, &op2->value.data.x_bigint);
8502 bigint_div_floor(&floor_result, &op1->value.data.x_bigint, &op2->value.data.x_bigint);
8503 if (bigint_cmp(&trunc_result, &floor_result) == CmpEQ) {
84238504 ok = true;
84248505 op_id = IrBinOpDivTrunc;
84258506 }
......@@ -8432,29 +8513,37 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
84328513 buf_ptr(&op2->value.type->name)));
84338514 return ira->codegen->builtin_types.entry_invalid;
84348515 }
8435 } else if (is_int) {
8516 } else {
84368517 op_id = IrBinOpDivTrunc;
84378518 }
84388519 } else if (op_id == IrBinOpRemUnspecified) {
8439 if (is_signed) {
8520 if (is_signed_div && (is_int || is_float)) {
84408521 bool ok = false;
84418522 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
8442 if ((is_int && op2->value.data.x_bignum.data.x_uint == 0) ||
8443 (!is_int && op2->value.data.x_bignum.data.x_float == 0.0))
8444 {
8445 // the division by zero error will be caught later, but we don't
8446 // have a remainder function ambiguity problem
8447 ok = true;
8448 } else {
8449 BigNum rem_result;
8450 BigNum mod_result;
8451 if (bignum_rem(&rem_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8452 zig_unreachable();
8523 if (is_int) {
8524 if (bigint_cmp_zero(&op2->value.data.x_bigint) == CmpEQ) {
8525 // the division by zero error will be caught later, but we don't
8526 // have a remainder function ambiguity problem
8527 ok = true;
8528 } else {
8529 BigInt rem_result;
8530 BigInt mod_result;
8531 bigint_rem(&rem_result, &op1->value.data.x_bigint, &op2->value.data.x_bigint);
8532 bigint_mod(&mod_result, &op1->value.data.x_bigint, &op2->value.data.x_bigint);
8533 ok = bigint_cmp(&rem_result, &mod_result) == CmpEQ;
84538534 }
8454 if (bignum_mod(&mod_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8455 zig_unreachable();
8535 } else {
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;
84568546 }
8457 ok = bignum_cmp_eq(&rem_result, &mod_result);
84588547 }
84598548 }
84608549 if (!ok) {
......@@ -8468,21 +8557,18 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
84688557 op_id = IrBinOpRemRem;
84698558 }
84708559
8471 if (resolved_type->id == TypeTableEntryIdInt ||
8472 resolved_type->id == TypeTableEntryIdNumLitInt)
8473 {
8560 if (is_int) {
84748561 // int
8475 } else if ((resolved_type->id == TypeTableEntryIdFloat ||
8476 resolved_type->id == TypeTableEntryIdNumLitFloat) &&
8562 } else if (is_float &&
84778563 (op_id == IrBinOpAdd ||
8478 op_id == IrBinOpSub ||
8479 op_id == IrBinOpMult ||
8480 op_id == IrBinOpDivUnspecified ||
8481 op_id == IrBinOpDivTrunc ||
8482 op_id == IrBinOpDivFloor ||
8483 op_id == IrBinOpDivExact ||
8484 op_id == IrBinOpRemRem ||
8485 op_id == IrBinOpRemMod))
8564 op_id == IrBinOpSub ||
8565 op_id == IrBinOpMult ||
8566 op_id == IrBinOpDivUnspecified ||
8567 op_id == IrBinOpDivTrunc ||
8568 op_id == IrBinOpDivFloor ||
8569 op_id == IrBinOpDivExact ||
8570 op_id == IrBinOpRemRem ||
8571 op_id == IrBinOpRemMod))
84868572 {
84878573 // float
84888574 } else {
......@@ -8494,6 +8580,18 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
84948580 return ira->codegen->builtin_types.entry_invalid;
84958581 }
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
84978595 IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, resolved_type);
84988596 if (casted_op1 == ira->codegen->invalid_instruction)
84998597 return ira->codegen->builtin_types.entry_invalid;
......@@ -8502,8 +8600,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
85028600 if (casted_op2 == ira->codegen->invalid_instruction)
85038601 return ira->codegen->builtin_types.entry_invalid;
85048602
8505
8506 if (casted_op1->value.special != ConstValSpecialRuntime && casted_op2->value.special != ConstValSpecialRuntime) {
8603 if (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2)) {
85078604 ConstExprValue *op1_val = &casted_op1->value;
85088605 ConstExprValue *op2_val = &casted_op2->value;
85098606 ConstExprValue *out_val = &bin_op_instruction->base.value;
......@@ -8704,17 +8801,17 @@ static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp
87048801 }
87058802
87068803 uint64_t old_array_len = array_type->data.array.len;
8804 uint64_t new_array_len;
87078805
8708 BigNum array_len;
8709 bignum_init_unsigned(&array_len, old_array_len);
8710 if (bignum_multiply_by_scalar(&array_len, mult_amt)) {
8806 if (__builtin_umulll_overflow((unsigned long long)old_array_len, (unsigned long long)mult_amt,
8807 (unsigned long long*)&new_array_len))
8808 {
87118809 ir_add_error(ira, &instruction->base, buf_sprintf("operation results in overflow"));
87128810 return ira->codegen->builtin_types.entry_invalid;
87138811 }
87148812
87158813 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
87168814
8717 uint64_t new_array_len = array_len.data.x_uint;
87188815 out_val->data.x_array.s_none.elements = create_const_vals(new_array_len);
87198816
87208817 expand_undef_array(ira->codegen, array_val);
......@@ -9581,9 +9678,10 @@ static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un
95819678
95829679 bool is_wrap_op = (un_op_instruction->op_id == IrUnOpNegationWrap);
95839680
9681 bool is_float = (expr_type->id == TypeTableEntryIdFloat || expr_type->id == TypeTableEntryIdNumLitFloat);
9682
95849683 if ((expr_type->id == TypeTableEntryIdInt && expr_type->data.integral.is_signed) ||
9585 expr_type->id == TypeTableEntryIdNumLitInt ||
9586 ((expr_type->id == TypeTableEntryIdFloat || expr_type->id == TypeTableEntryIdNumLitFloat) && !is_wrap_op))
9684 expr_type->id == TypeTableEntryIdNumLitInt || (is_float && !is_wrap_op))
95879685 {
95889686 if (instr_is_comptime(value)) {
95899687 ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
......@@ -9591,19 +9689,19 @@ static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un
95919689 return ira->codegen->builtin_types.entry_invalid;
95929690
95939691 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);
9595 if (expr_type->id == TypeTableEntryIdFloat ||
9596 expr_type->id == TypeTableEntryIdNumLitFloat ||
9597 expr_type->id == TypeTableEntryIdNumLitInt)
9598 {
9692 if (is_float) {
9693 bigfloat_negate(&out_val->data.x_bigfloat, &target_const_val->data.x_bigfloat);
9694 } else if (is_wrap_op) {
9695 bigint_negate_wrap(&out_val->data.x_bigint, &target_const_val->data.x_bigint,
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) {
95999701 return expr_type;
96009702 }
96019703
9602 bool overflow = !bignum_fits_in_bits(&out_val->data.x_bignum, 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) {
9704 if (!bigint_fits_in_bits(&out_val->data.x_bigint, expr_type->data.integral.bit_count, true)) {
96079705 ir_add_error(ira, &un_op_instruction->base, buf_sprintf("negation caused overflow"));
96089706 return ira->codegen->builtin_types.entry_invalid;
96099707 }
......@@ -9632,7 +9730,7 @@ static TypeTableEntry *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *ins
96329730 return ira->codegen->builtin_types.entry_invalid;
96339731
96349732 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,
96369734 expr_type->data.integral.bit_count, expr_type->data.integral.is_signed);
96379735 return expr_type;
96389736 }
......@@ -9887,12 +9985,12 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
98879985 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
98889986 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0);
98899987 } else {
9890 ConstExprValue *elem_val = ir_resolve_const(ira, elem_index, UndefBad);
9891 if (!elem_val)
9988 uint64_t elem_val_scalar;
9989 if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))
98929990 return ira->codegen->builtin_types.entry_invalid;
98939991
98949992 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
98979995 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
98989996 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
990910007 ConstExprValue *args_val = const_ptr_pointee(ira->codegen, ptr_val);
991010008 size_t start = args_val->data.x_arg_tuple.start_index;
991110009 size_t end = args_val->data.x_arg_tuple.end_index;
9912 ConstExprValue *elem_index_val = ir_resolve_const(ira, elem_index, UndefBad);
9913 if (!elem_index_val)
10010 uint64_t elem_index_val;
10011 if (!ir_resolve_usize(ira, elem_index, &elem_index_val))
991410012 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;
991610014 size_t len = end - start;
991710015 if (index >= len) {
991810016 ir_add_error(ira, &elem_ptr_instruction->base,
......@@ -9945,7 +10043,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
994510043
994610044 bool safety_check_on = elem_ptr_instruction->safety_check_on;
994710045 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);
994910047 if (array_type->id == TypeTableEntryIdArray) {
995010048 uint64_t array_len = array_type->data.array.len;
995110049 if (index >= array_len) {
......@@ -10021,7 +10119,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
1002110119 }
1002210120 ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];
1002310121 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);
1002510123 if (index >= slice_len) {
1002610124 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
1002710125 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,
1110711205 {
1110811206 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
1110911207 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);
1111111209 return ira->codegen->builtin_types.entry_num_lit_int;
1111211210 }
1111311211 }
......@@ -11213,10 +11311,10 @@ static TypeTableEntry *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionC
1121311311 return ira->codegen->builtin_types.entry_invalid;
1121411312 } else if (value->value.type->id == TypeTableEntryIdInt) {
1121511313 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,
1121711315 value->value.type->data.integral.bit_count);
1121811316 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);
1122011318 return value->value.type;
1122111319 }
1122211320
......@@ -11235,10 +11333,10 @@ static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionC
1123511333 return ira->codegen->builtin_types.entry_invalid;
1123611334 } else if (value->value.type->id == TypeTableEntryIdInt) {
1123711335 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,
1123911337 value->value.type->data.integral.bit_count);
1124011338 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);
1124211340 return value->value.type;
1124311341 }
1124411342
......@@ -11272,7 +11370,7 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_
1127211370 source_instr->scope, source_instr->source_node);
1127311371 const_instruction->base.value.type = tag_type;
1127411372 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);
1127611374 return &const_instruction->base;
1127711375 }
1127811376
......@@ -11441,7 +11539,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1144111539 TypeTableEntry *tag_type = target_type->data.enumeration.tag_type;
1144211540 if (pointee_val) {
1144311541 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);
1144511543 return tag_type;
1144611544 }
1144711545
......@@ -11490,9 +11588,9 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
1149011588 if (!prong_val)
1149111589 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;
1149411592 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)];
1149611594 } else if (prong_value->value.type->id == TypeTableEntryIdEnum) {
1149711595 field = &target_type->data.enumeration.fields[prong_val->data.x_enum.tag];
1149811596 } else {
......@@ -11619,7 +11717,7 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,
1161911717 ConstExprValue *len_val = &array_value->value.data.x_struct.fields[slice_len_index];
1162011718 if (len_val->special != ConstValSpecialRuntime) {
1162111719 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));
1162311721 }
1162411722 }
1162511723 TypeStructField *field = &type_entry->data.structure.fields[slice_len_index];
......@@ -11866,7 +11964,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
1186611964
1186711965 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);
1187011968 TypeEnumField *field = &enum_type->data.enumeration.fields[tag_uint];
1187111969 TypeTableEntry *this_field_type = field->type_entry;
1187211970
......@@ -12063,7 +12161,7 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn
1206312161
1206412162 if (instr_is_comptime(target)) {
1206512163 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);
1206712165 TypeEnumField *field = &enum_type->data.enumeration.fields[tag_value];
1206812166 ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);
1206912167 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
......@@ -12197,7 +12295,7 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira,
1219712295
1219812296 size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, container_type->type_ref, field->gen_index);
1219912297 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);
1220112299 return ira->codegen->builtin_types.entry_num_lit_int;
1220212300}
1220312301
......@@ -12506,8 +12604,8 @@ static TypeTableEntry *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruc
1250612604
1250712605 if (target->value.special == ConstValSpecialStatic) {
1250812606 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
12509 bignum_init_bignum(&out_val->data.x_bignum, &target->value.data.x_bignum);
12510 bignum_truncate(&out_val->data.x_bignum, dest_type->data.integral.bit_count);
12607 bigint_truncate(&out_val->data.x_bigint, &target->value.data.x_bigint, dest_type->data.integral.bit_count,
12608 dest_type->data.integral.is_signed);
1251112609 return dest_type;
1251212610 }
1251312611
......@@ -12619,7 +12717,7 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi
1261912717 zig_unreachable();
1262012718 }
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);
1262312721 size_t end = start + count;
1262412722 if (end > bound_end) {
1262512723 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
1268112779 casted_count->value.special == ConstValSpecialStatic &&
1268212780 casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr)
1268312781 {
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
1268612784 ConstExprValue *dest_ptr_val = &casted_dest_ptr->value;
1268712785 ConstExprValue *dest_elements;
......@@ -12868,21 +12966,21 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
1286812966 case ConstPtrSpecialBaseArray:
1286912967 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
1287012968 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);
1287212970 break;
1287312971 case ConstPtrSpecialBaseStruct:
1287412972 zig_panic("TODO slice const inner struct");
1287512973 case ConstPtrSpecialHardCodedAddr:
1287612974 array_val = nullptr;
1287712975 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);
1287912977 break;
1288012978 }
1288112979 } else {
1288212980 zig_unreachable();
1288312981 }
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);
1288612984 if (start_scalar > rel_end) {
1288712985 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
1288812986 return ira->codegen->builtin_types.entry_invalid;
......@@ -12890,7 +12988,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
1289012988
1289112989 uint64_t end_scalar;
1289212990 if (end) {
12893 end_scalar = end->value.data.x_bignum.data.x_uint;
12991 end_scalar = bigint_as_unsigned(&end->value.data.x_bigint);
1289412992 } else {
1289512993 end_scalar = rel_end;
1289612994 }
......@@ -12970,7 +13068,7 @@ static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrIns
1297013068 }
1297113069
1297213070 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);
1297413072 return ira->codegen->builtin_types.entry_num_lit_int;
1297513073}
1297613074
......@@ -13011,7 +13109,7 @@ static TypeTableEntry *ir_analyze_instruction_alignof(IrAnalyze *ira, IrInstruct
1301113109 } else {
1301213110 uint64_t align_in_bytes = LLVMABIAlignmentOfType(ira->codegen->target_data_ref, type_entry->type_ref);
1301313111 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);
1301513113 return ira->codegen->builtin_types.entry_num_lit_int;
1301613114 }
1301713115}
......@@ -13060,29 +13158,32 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst
1306013158 casted_result_ptr->value.special == ConstValSpecialStatic)
1306113159 {
1306213160 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13063 BigNum *op1_bignum = &casted_op1->value.data.x_bignum;
13064 BigNum *op2_bignum = &casted_op2->value.data.x_bignum;
13161 BigInt *op1_bigint = &casted_op1->value.data.x_bigint;
13162 BigInt *op2_bigint = &casted_op2->value.data.x_bigint;
1306513163 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;
1306713165 switch (instruction->op) {
1306813166 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);
1307013168 break;
1307113169 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);
1307313171 break;
1307413172 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);
1307613174 break;
1307713175 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);
1307913177 break;
1308013178 }
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,
1308213180 dest_type->data.integral.is_signed))
1308313181 {
1308413182 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);
1308613187 }
1308713188 pointee_val->special = ConstValSpecialStatic;
1308813189 return ira->codegen->builtin_types.entry_bool;
......@@ -13301,14 +13402,14 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
1330113402 size_t start_index;
1330213403 size_t end_index;
1330313404 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);
1330513406 } else if (start_value->value.type->id == TypeTableEntryIdEnum) {
1330613407 start_index = start_value->value.data.x_enum.tag;
1330713408 } else {
1330813409 zig_unreachable();
1330913410 }
1331013411 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);
1331213413 } else if (end_value->value.type->id == TypeTableEntryIdEnum) {
1331313414 end_index = end_value->value.data.x_enum.tag;
1331413415 } else {
......@@ -13357,7 +13458,7 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
1335713458 if (!end_val)
1335813459 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,
1336113462 start_value->source_node);
1336213463 if (prev_node != nullptr) {
1336313464 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
1336613467 }
1336713468 }
1336813469 if (!instruction->have_else_prong) {
13369 BigNum min_val;
13470 BigInt min_val;
1337013471 eval_min_max_value_int(ira->codegen, switch_type, &min_val, false);
13371 BigNum max_val;
13472 BigInt max_val;
1337213473 eval_min_max_value_int(ira->codegen, switch_type, &max_val, true);
1337313474 if (!rangeset_spans(&rs, &min_val, &max_val)) {
1337413475 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
1350313604 buf[0] = val->data.x_bool ? 1 : 0;
1350413605 return;
1350513606 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);
1350713609 return;
1350813610 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);
1351013613 return;
1351113614 case TypeTableEntryIdPointer:
1351213615 if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
13513 BigNum bn;
13514 bignum_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);
13616 BigInt bn;
13617 bigint_init_unsigned(&bn, val->data.x_ptr.data.hard_coded_addr.addr);
13618 bigint_write_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, codegen->is_big_endian);
1351613619 return;
1351713620 } else {
1351813621 zig_unreachable();
......@@ -13562,18 +13665,20 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
1356213665 val->data.x_bool = (buf[0] != 0);
1356313666 return;
1356413667 case TypeTableEntryIdInt:
13565 bignum_read_twos_complement(&val->data.x_bignum, buf, val->type->data.integral.bit_count, codegen->is_big_endian,
13566 val->type->data.integral.is_signed);
13668 bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
13669 codegen->is_big_endian, val->type->data.integral.is_signed);
1356713670 return;
1356813671 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);
1357013674 return;
1357113675 case TypeTableEntryIdPointer:
1357213676 {
1357313677 val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
13574 BigNum bn;
13575 bignum_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, codegen->is_big_endian, false);
13576 val->data.x_ptr.data.hard_coded_addr.addr = bignum_to_twos_complement(&bn);
13678 BigInt bn;
13679 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,
13680 codegen->is_big_endian, false);
13681 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
1357713682 return;
1357813683 }
1357913684 case TypeTableEntryIdArray:
......@@ -13729,7 +13834,7 @@ static TypeTableEntry *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstr
1372913834
1373013835 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
1373113836 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);
1373313838 return dest_type;
1373413839 }
1373513840
src/os.hpp+1
......@@ -13,6 +13,7 @@
1313#include "error.hpp"
1414
1515#include <stdio.h>
16#include <inttypes.h>
1617
1718enum TerminationId {
1819 TerminationIdClean,
src/parser.cpp+22-9
......@@ -186,9 +186,14 @@ static Buf *token_buf(Token *token) {
186186 return &token->data.str_lit.str;
187187}
188188
189static BigNum *token_bignum(Token *token) {
190 assert(token->id == TokenIdNumberLiteral);
191 return &token->data.num_lit.bignum;
189static BigInt *token_bigint(Token *token) {
190 assert(token->id == TokenIdIntLiteral);
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;
192197}
193198
194199static uint8_t token_char_lit(Token *token) {
......@@ -660,16 +665,21 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
660665}
661666
662667/*
663PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
668PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
664669KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"
665670*/
666671static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
667672 Token *token = &pc->tokens->at(*token_index);
668673
669 if (token->id == TokenIdNumberLiteral) {
670 AstNode *node = ast_create_node(pc, NodeTypeNumberLiteral, token);
671 node->data.number_literal.bignum = token_bignum(token);
672 node->data.number_literal.overflow = token->data.num_lit.overflow;
674 if (token->id == TokenIdIntLiteral) {
675 AstNode *node = ast_create_node(pc, NodeTypeIntLiteral, token);
676 node->data.int_literal.bigint = token_bigint(token);
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;
673683 *token_index += 1;
674684 return node;
675685 } else if (token->id == TokenIdStringLiteral) {
......@@ -2629,7 +2639,10 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
26292639 visit_field(&node->data.unwrap_err_expr.symbol, visit, context);
26302640 visit_field(&node->data.unwrap_err_expr.op2, visit, context);
26312641 break;
2632 case NodeTypeNumberLiteral:
2642 case NodeTypeIntLiteral:
2643 // none
2644 break;
2645 case NodeTypeFloatLiteral:
26332646 // none
26342647 break;
26352648 case NodeTypeStringLiteral:
src/range_set.cpp+15-17
......@@ -1,11 +1,11 @@
11#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) {
44 for (size_t i = 0; i < rs->src_range_list.length; i += 1) {
55 RangeWithSrc *range_with_src = &rs->src_range_list.at(i);
66 Range *range = &range_with_src->range;
7 if ((bignum_cmp_gte(first, &range->first) && bignum_cmp_lte(first, &range->last)) ||
8 (bignum_cmp_gte(last, &range->first) && bignum_cmp_lte(last, &range->last)))
7 if ((bigint_cmp(first, &range->first) != CmpLT && bigint_cmp(first, &range->last) != CmpGT) ||
8 (bigint_cmp(last, &range->first) != CmpLT && bigint_cmp(last, &range->last) != CmpGT))
99 {
1010 return range_with_src->source_node;
1111 }
......@@ -16,24 +16,22 @@ AstNode *rangeset_add_range(RangeSet *rs, BigNum *first, BigNum *last, AstNode *
1616
1717}
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) {
2020 for (size_t i = 0; i < list->length; i += 1) {
2121 Range *range = &list->at(i);
2222
23 BigNum first_minus_one;
24 if (bignum_sub(&first_minus_one, &range->first, one))
25 zig_unreachable();
23 BigInt first_minus_one;
24 bigint_sub(&first_minus_one, &range->first, one);
2625
27 if (bignum_cmp_eq(&new_range->last, &first_minus_one)) {
26 if (bigint_cmp(&new_range->last, &first_minus_one) == CmpEQ) {
2827 range->first = new_range->first;
2928 return true;
3029 }
3130
32 BigNum last_plus_one;
33 if (bignum_add(&last_plus_one, &range->last, one))
34 zig_unreachable();
31 BigInt last_plus_one;
32 bigint_add(&last_plus_one, &range->last, one);
3533
36 if (bignum_cmp_eq(&new_range->first, &last_plus_one)) {
34 if (bigint_cmp(&new_range->first, &last_plus_one) == CmpEQ) {
3735 range->last = new_range->last;
3836 return true;
3937 }
......@@ -42,7 +40,7 @@ static bool add_range(ZigList<Range> *list, Range *new_range, BigNum *one) {
4240 return false;
4341}
4442
45bool rangeset_spans(RangeSet *rs, BigNum *first, BigNum *last) {
43bool rangeset_spans(RangeSet *rs, BigInt *first, BigInt *last) {
4644 ZigList<Range> cur_list_value = {0};
4745 ZigList<Range> other_list_value = {0};
4846 ZigList<Range> *cur_list = &cur_list_value;
......@@ -54,8 +52,8 @@ bool rangeset_spans(RangeSet *rs, BigNum *first, BigNum *last) {
5452 cur_list->append({range->first, range->last});
5553 }
5654
57 BigNum one;
58 bignum_init_unsigned(&one, 1);
55 BigInt one;
56 bigint_init_unsigned(&one, 1);
5957
6058 bool changes_made = true;
6159 while (changes_made) {
......@@ -73,9 +71,9 @@ bool rangeset_spans(RangeSet *rs, BigNum *first, BigNum *last) {
7371 if (cur_list->length != 1)
7472 return false;
7573 Range *range = &cur_list->at(0);
76 if (bignum_cmp_neq(&range->first, first))
74 if (bigint_cmp(&range->first, first) != CmpEQ)
7775 return false;
78 if (bignum_cmp_neq(&range->last, last))
76 if (bigint_cmp(&range->last, last) != CmpEQ)
7977 return false;
8078 return true;
8179}
src/range_set.hpp+4-4
......@@ -11,8 +11,8 @@
1111#include "all_types.hpp"
1212
1313struct Range {
14 BigNum first;
15 BigNum last;
14 BigInt first;
15 BigInt last;
1616};
1717
1818struct RangeWithSrc {
......@@ -24,7 +24,7 @@ struct RangeSet {
2424 ZigList<RangeWithSrc> src_range_list;
2525};
2626
27AstNode *rangeset_add_range(RangeSet *rs, BigNum *first, BigNum *last, AstNode *source_node);
28bool rangeset_spans(RangeSet *rs, BigNum *first, BigNum *last);
27AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode *source_node);
28bool rangeset_spans(RangeSet *rs, BigInt *first, BigInt *last);
2929
3030#endif
src/tokenizer.cpp+87-58
......@@ -225,13 +225,13 @@ struct Tokenize {
225225 uint32_t radix;
226226 int32_t exp_add_amt;
227227 bool is_exp_negative;
228 bool is_num_lit_float;
229228 size_t char_code_index;
230229 size_t char_code_end;
231230 bool unicode;
232231 uint32_t char_code;
233232 int exponent_in_bin_or_dec;
234 BigNum specified_exponent;
233 BigInt specified_exponent;
234 BigInt significand;
235235};
236236
237237__attribute__ ((format (printf, 2, 3)))
......@@ -255,8 +255,11 @@ static void tokenize_error(Tokenize *t, const char *format, ...) {
255255static void set_token_id(Tokenize *t, Token *token, TokenId id) {
256256 token->id = id;
257257
258 if (id == TokenIdNumberLiteral) {
259 token->data.num_lit.overflow = false;
258 if (id == TokenIdIntLiteral) {
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;
260263 } else if (id == TokenIdStringLiteral || id == TokenIdSymbol) {
261264 memset(&token->data.str_lit.str, 0, sizeof(Buf));
262265 buf_resize(&token->data.str_lit.str, 0);
......@@ -283,34 +286,40 @@ static void cancel_token(Tokenize *t) {
283286}
284287
285288static void end_float_token(Tokenize *t) {
286 t->cur_tok->data.num_lit.bignum.kind = BigNumKindFloat;
287
288289 if (t->radix == 10) {
289 char *str_begin = buf_ptr(t->buf) + t->cur_tok->start_pos;
290 char *str_end;
291 errno = 0;
292 t->cur_tok->data.num_lit.bignum.data.x_float = strtod(str_begin, &str_end);
293 if (errno) {
294 t->cur_tok->data.num_lit.overflow = true;
295 return;
290 uint8_t *ptr_buf = (uint8_t*)buf_ptr(t->buf) + t->cur_tok->start_pos;
291 size_t buf_len = t->cur_tok->end_pos - t->cur_tok->start_pos;
292 if (bigfloat_init_buf_base10(&t->cur_tok->data.float_lit.bigfloat, ptr_buf, buf_len)) {
293 t->cur_tok->data.float_lit.overflow = true;
296294 }
297 assert(str_end <= buf_ptr(t->buf) + t->cur_tok->end_pos);
298295 return;
299296 }
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) {
303 t->cur_tok->data.num_lit.overflow = true;
306 if (!bigint_fits_in_bits(&t->specified_exponent, 64, true)) {
307 t->cur_tok->data.float_lit.overflow = true;
304308 return;
305309 }
306310
307 int64_t specified_exponent = t->specified_exponent.data.x_uint;
311 int64_t specified_exponent = bigint_as_signed(&t->specified_exponent);
308312 if (t->is_exp_negative) {
309313 specified_exponent = -specified_exponent;
310314 }
311315 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);
314323 uint64_t significand_bits;
315324 uint64_t exponent_bits;
316325 if (significand == 0) {
......@@ -325,7 +334,7 @@ static void end_float_token(Tokenize *t) {
325334 int significand_magnitude_in_bin = __builtin_clzll(1) - __builtin_clzll(significand);
326335 t->exponent_in_bin_or_dec += significand_magnitude_in_bin;
327336 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;
329338 return;
330339 } else {
331340 // this should chop off exactly one 1 bit from the top.
......@@ -335,20 +344,17 @@ static void end_float_token(Tokenize *t) {
335344 }
336345 }
337346 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);
339350}
340351
341352static void end_token(Tokenize *t) {
342353 assert(t->cur_tok);
343354 t->cur_tok->end_pos = t->pos + 1;
344355
345 if (t->cur_tok->id == TokenIdNumberLiteral) {
346 if (t->cur_tok->data.num_lit.overflow) {
347 return;
348 }
349 if (t->is_num_lit_float) {
350 end_float_token(t);
351 }
356 if (t->cur_tok->id == TokenIdFloatLiteral) {
357 end_float_token(t);
352358 } else if (t->cur_tok->id == TokenIdSymbol) {
353359 char *token_mem = buf_ptr(t->buf) + t->cur_tok->start_pos;
354360 int token_len = (int)(t->cur_tok->end_pos - t->cur_tok->start_pos);
......@@ -428,23 +434,21 @@ void tokenize(Buf *buf, Tokenization *out) {
428434 break;
429435 case '0':
430436 t.state = TokenizeStateZero;
431 begin_token(&t, TokenIdNumberLiteral);
437 begin_token(&t, TokenIdIntLiteral);
432438 t.radix = 10;
433439 t.exp_add_amt = 1;
434440 t.exponent_in_bin_or_dec = 0;
435 t.is_num_lit_float = false;
436 bignum_init_unsigned(&t.cur_tok->data.num_lit.bignum, 0);
437 bignum_init_unsigned(&t.specified_exponent, 0);
441 bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, 0);
442 bigint_init_unsigned(&t.specified_exponent, 0);
438443 break;
439444 case DIGIT_NON_ZERO:
440445 t.state = TokenizeStateNumber;
441 begin_token(&t, TokenIdNumberLiteral);
446 begin_token(&t, TokenIdIntLiteral);
442447 t.radix = 10;
443448 t.exp_add_amt = 1;
444449 t.exponent_in_bin_or_dec = 0;
445 t.is_num_lit_float = false;
446 bignum_init_unsigned(&t.cur_tok->data.num_lit.bignum, get_digit_value(c));
447 bignum_init_unsigned(&t.specified_exponent, 0);
450 bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, get_digit_value(c));
451 bigint_init_unsigned(&t.specified_exponent, 0);
448452 break;
449453 case '"':
450454 begin_token(&t, TokenIdStringLiteral);
......@@ -1182,7 +1186,9 @@ void tokenize(Buf *buf, Tokenization *out) {
11821186 }
11831187 if (is_exponent_signifier(c, t.radix)) {
11841188 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);
11861192 break;
11871193 }
11881194 uint32_t digit_value = get_digit_value(c);
......@@ -1196,23 +1202,33 @@ void tokenize(Buf *buf, Tokenization *out) {
11961202 t.state = TokenizeStateStart;
11971203 continue;
11981204 }
1199 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||
1200 bignum_multiply_by_scalar(&t.cur_tok->data.num_lit.bignum, t.radix);
1201 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||
1202 bignum_increment_by_scalar(&t.cur_tok->data.num_lit.bignum, digit_value);
1205 BigInt digit_value_bi;
1206 bigint_init_unsigned(&digit_value_bi, digit_value);
1207
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);
12031215 break;
12041216 }
12051217 case TokenizeStateNumberDot:
1206 if (c == '.') {
1207 t.pos -= 2;
1208 end_token(&t);
1209 t.state = TokenizeStateStart;
1218 {
1219 if (c == '.') {
1220 t.pos -= 2;
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);
12101230 continue;
12111231 }
1212 t.pos -= 1;
1213 t.state = TokenizeStateFloatFraction;
1214 t.is_num_lit_float = true;
1215 continue;
12161232 case TokenizeStateFloatFraction:
12171233 {
12181234 if (is_exponent_signifier(c, t.radix)) {
......@@ -1236,10 +1252,16 @@ void tokenize(Buf *buf, Tokenization *out) {
12361252 // end of the token.
12371253 break;
12381254 }
1239 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||
1240 bignum_multiply_by_scalar(&t.cur_tok->data.num_lit.bignum, t.radix);
1241 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||
1242 bignum_increment_by_scalar(&t.cur_tok->data.num_lit.bignum, digit_value);
1255 BigInt digit_value_bi;
1256 bigint_init_unsigned(&digit_value_bi, digit_value);
1257
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);
12431265 break;
12441266 }
12451267 case TokenizeStateFloatExponentUnsigned:
......@@ -1278,10 +1300,16 @@ void tokenize(Buf *buf, Tokenization *out) {
12781300 // end of the token.
12791301 break;
12801302 }
1281 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||
1282 bignum_multiply_by_scalar(&t.specified_exponent, 10);
1283 t.cur_tok->data.num_lit.overflow = t.cur_tok->data.num_lit.overflow ||
1284 bignum_increment_by_scalar(&t.specified_exponent, digit_value);
1303 BigInt digit_value_bi;
1304 bigint_init_unsigned(&digit_value_bi, digit_value);
1305
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);
12851313 }
12861314 break;
12871315 case TokenizeStateSawDash:
......@@ -1441,11 +1469,13 @@ const char * token_name(TokenId id) {
14411469 case TokenIdDivEq: return "/=";
14421470 case TokenIdDot: return ".";
14431471 case TokenIdDoubleQuestion: return "??";
1444 case TokenIdEllipsis3: return "...";
14451472 case TokenIdEllipsis2: return "..";
1473 case TokenIdEllipsis3: return "...";
14461474 case TokenIdEof: return "EOF";
14471475 case TokenIdEq: return "=";
14481476 case TokenIdFatArrow: return "=>";
1477 case TokenIdFloatLiteral: return "FloatLiteral";
1478 case TokenIdIntLiteral: return "IntLiteral";
14491479 case TokenIdKeywordAnd: return "and";
14501480 case TokenIdKeywordAsm: return "asm";
14511481 case TokenIdKeywordBreak: return "break";
......@@ -1494,7 +1524,6 @@ const char * token_name(TokenId id) {
14941524 case TokenIdMinusPercent: return "-%";
14951525 case TokenIdMinusPercentEq: return "-%=";
14961526 case TokenIdModEq: return "%=";
1497 case TokenIdNumberLiteral: return "NumberLiteral";
14981527 case TokenIdNumberSign: return "#";
14991528 case TokenIdPercent: return "%";
15001529 case TokenIdPercentDot: return "%.";
src/tokenizer.hpp+18-9
......@@ -9,7 +9,8 @@
99#define ZIG_TOKENIZER_HPP
1010
1111#include "buffer.hpp"
12#include "bignum.hpp"
12#include "bigint.hpp"
13#include "bigfloat.hpp"
1314
1415enum TokenId {
1516 TokenIdAmpersand,
......@@ -40,11 +41,13 @@ enum TokenId {
4041 TokenIdDivEq,
4142 TokenIdDot,
4243 TokenIdDoubleQuestion,
43 TokenIdEllipsis3,
4444 TokenIdEllipsis2,
45 TokenIdEllipsis3,
4546 TokenIdEof,
4647 TokenIdEq,
4748 TokenIdFatArrow,
49 TokenIdFloatLiteral,
50 TokenIdIntLiteral,
4851 TokenIdKeywordAnd,
4952 TokenIdKeywordAsm,
5053 TokenIdKeywordBreak,
......@@ -93,7 +96,6 @@ enum TokenId {
9396 TokenIdMinusPercent,
9497 TokenIdMinusPercentEq,
9598 TokenIdModEq,
96 TokenIdNumberLiteral,
9799 TokenIdNumberSign,
98100 TokenIdPercent,
99101 TokenIdPercentDot,
......@@ -118,13 +120,17 @@ enum TokenId {
118120 TokenIdTimesPercentEq,
119121};
120122
121struct TokenNumLit {
122 BigNum bignum;
123 // overflow is true if when parsing the number, we discovered it would not
124 // fit without losing data in a uint64_t or double
123struct TokenFloatLit {
124 BigFloat bigfloat;
125 // overflow is true if when parsing the number, we discovered it would not fit
126 // without losing data
125127 bool overflow;
126128};
127129
130struct TokenIntLit {
131 BigInt bigint;
132};
133
128134struct TokenStrLit {
129135 Buf str;
130136 bool is_c_str;
......@@ -142,8 +148,11 @@ struct Token {
142148 size_t start_column;
143149
144150 union {
145 // TokenIdNumberLiteral
146 TokenNumLit num_lit;
151 // TokenIdIntLiteral
152 TokenIntLit int_lit;
153
154 // TokenIdFloatLiteral
155 TokenFloatLit float_lit;
147156
148157 // TokenIdStringLiteral or TokenIdSymbol
149158 TokenStrLit str_lit;
std/math/fabs.zig+2-2
......@@ -36,8 +36,8 @@ test "math.fabs" {
3636}
3737
3838test "math.fabs32" {
39 assert(fabs64(1.0) == 1.0);
40 assert(fabs64(-1.0) == 1.0);
39 assert(fabs32(1.0) == 1.0);
40 assert(fabs32(-1.0) == 1.0);
4141}
4242
4343test "math.fabs64" {
std/math/log10.zig+1-1
......@@ -139,7 +139,7 @@ fn log10_64(x_: f64) -> f64 {
139139 // hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f)
140140 var hi = f - hfsq;
141141 var hii = @bitCast(u64, hi);
142 hii &= @maxValue(u64) << 32;
142 hii &= u64(@maxValue(u64)) <<% 32;
143143 hi = @bitCast(f64, hii);
144144 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 {
133133 // hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f)
134134 var hi = f - hfsq;
135135 var hii = @bitCast(u64, hi);
136 hii &= @maxValue(u64) << 32;
136 hii &= u64(@maxValue(u64)) <<% 32;
137137 hi = @bitCast(f64, hii);
138138 const lo = f - hi - hfsq + s * (hfsq + R);
139139
test/cases/math.zig+28-6
......@@ -58,15 +58,33 @@ test "@shlWithOverflow" {
5858}
5959
6060test "@clz" {
61 assert(@clz(u8(0b00001010)) == 4);
62 assert(@clz(u8(0b10001010)) == 0);
63 assert(@clz(u8(0b00000000)) == 8);
61 testClz();
62 comptime testClz();
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)
6473}
6574
6675test "@ctz" {
67 assert(@ctz(u8(0b10100000)) == 5);
68 assert(@ctz(u8(0b10001010)) == 1);
69 assert(@ctz(u8(0b00000000)) == 8);
76 testCtz();
77 comptime testCtz();
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)
7088}
7189
7290test "assignment operators" {
......@@ -229,3 +247,7 @@ test "allow signed integer division/remainder when values are comptime known and
229247 assert(5 % 3 == 2);
230248 assert(-6 % 3 == 0);
231249}
250
251test "float literal parsing" {
252 comptime assert(0x1.0 == 1.0);
253}