| ... | ... | @@ -99,14 +99,78 @@ static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) { |
| 99 | 99 | } |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | static uint64_t max_unsigned_val(TypeTableEntry *type_entry) { |
| 103 | assert(type_entry->id == TypeTableEntryIdInt); |
| 104 | if (type_entry->data.integral.bit_count == 64) { |
| 105 | return UINT64_MAX; |
| 106 | } else if (type_entry->data.integral.bit_count == 32) { |
| 107 | return UINT32_MAX; |
| 108 | } else if (type_entry->data.integral.bit_count == 16) { |
| 109 | return UINT16_MAX; |
| 110 | } else if (type_entry->data.integral.bit_count == 8) { |
| 111 | return UINT8_MAX; |
| 112 | } else { |
| 113 | zig_unreachable(); |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | static int64_t max_signed_val(TypeTableEntry *type_entry) { |
| 118 | assert(type_entry->id == TypeTableEntryIdInt); |
| 119 | if (type_entry->data.integral.bit_count == 64) { |
| 120 | return INT64_MAX; |
| 121 | } else if (type_entry->data.integral.bit_count == 32) { |
| 122 | return INT32_MAX; |
| 123 | } else if (type_entry->data.integral.bit_count == 16) { |
| 124 | return INT16_MAX; |
| 125 | } else if (type_entry->data.integral.bit_count == 8) { |
| 126 | return INT8_MAX; |
| 127 | } else { |
| 128 | zig_unreachable(); |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | static int64_t min_signed_val(TypeTableEntry *type_entry) { |
| 133 | assert(type_entry->id == TypeTableEntryIdInt); |
| 134 | if (type_entry->data.integral.bit_count == 64) { |
| 135 | return INT64_MIN; |
| 136 | } else if (type_entry->data.integral.bit_count == 32) { |
| 137 | return INT32_MIN; |
| 138 | } else if (type_entry->data.integral.bit_count == 16) { |
| 139 | return INT16_MIN; |
| 140 | } else if (type_entry->data.integral.bit_count == 8) { |
| 141 | return INT8_MIN; |
| 142 | } else { |
| 143 | zig_unreachable(); |
| 144 | } |
| 145 | } |
| 146 | |
| 102 | 147 | static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val, |
| 103 | | ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *)) |
| 148 | ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), |
| 149 | TypeTableEntry *type) |
| 104 | 150 | { |
| 105 | 151 | bool overflow = bignum_fn(&out_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum); |
| 106 | 152 | if (overflow) { |
| 107 | 153 | return ErrorOverflow; |
| 108 | 154 | } |
| 109 | 155 | |
| 156 | if (type->id == TypeTableEntryIdInt && !bignum_fits_in_bits(&out_val->data.x_bignum, |
| 157 | type->data.integral.bit_count, type->data.integral.is_signed)) |
| 158 | { |
| 159 | if (type->data.integral.is_wrapping) { |
| 160 | if (type->data.integral.is_signed) { |
| 161 | out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1; |
| 162 | out_val->data.x_bignum.is_negative = !out_val->data.x_bignum.is_negative; |
| 163 | } else if (out_val->data.x_bignum.is_negative) { |
| 164 | out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1; |
| 165 | out_val->data.x_bignum.is_negative = false; |
| 166 | } else { |
| 167 | bignum_truncate(&out_val->data.x_bignum, type->data.integral.bit_count); |
| 168 | } |
| 169 | } else { |
| 170 | return ErrorOverflow; |
| 171 | } |
| 172 | } |
| 173 | |
| 110 | 174 | out_val->ok = true; |
| 111 | 175 | out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var; |
| 112 | 176 | return 0; |
| ... | ... | @@ -117,6 +181,8 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, |
| 117 | 181 | { |
| 118 | 182 | assert(op1_val->ok); |
| 119 | 183 | assert(op2_val->ok); |
| 184 | assert(op1_type->id != TypeTableEntryIdInvalid); |
| 185 | assert(op2_type->id != TypeTableEntryIdInvalid); |
| 120 | 186 | |
| 121 | 187 | switch (bin_op) { |
| 122 | 188 | case BinOpTypeAssign: |
| ... | ... | @@ -132,8 +198,7 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, |
| 132 | 198 | case BinOpTypeAssignBitOr: |
| 133 | 199 | case BinOpTypeAssignBoolAnd: |
| 134 | 200 | case BinOpTypeAssignBoolOr: |
| 135 | | out_val->ok = true; |
| 136 | | return 0; |
| 201 | zig_unreachable(); |
| 137 | 202 | case BinOpTypeBoolOr: |
| 138 | 203 | case BinOpTypeBoolAnd: |
| 139 | 204 | assert(op1_type->id == TypeTableEntryIdBool); |
| ... | ... | @@ -191,21 +256,21 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, |
| 191 | 256 | return 0; |
| 192 | 257 | } |
| 193 | 258 | case BinOpTypeAdd: |
| 194 | | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add); |
| 259 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add, op1_type); |
| 195 | 260 | case BinOpTypeBinOr: |
| 196 | | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_or); |
| 261 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_or, op1_type); |
| 197 | 262 | case BinOpTypeBinXor: |
| 198 | | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_xor); |
| 263 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_xor, op1_type); |
| 199 | 264 | case BinOpTypeBinAnd: |
| 200 | | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_and); |
| 265 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_and, op1_type); |
| 201 | 266 | case BinOpTypeBitShiftLeft: |
| 202 | | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl); |
| 267 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type); |
| 203 | 268 | case BinOpTypeBitShiftRight: |
| 204 | | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shr); |
| 269 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shr, op1_type); |
| 205 | 270 | case BinOpTypeSub: |
| 206 | | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub); |
| 271 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type); |
| 207 | 272 | case BinOpTypeMult: |
| 208 | | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul); |
| 273 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type); |
| 209 | 274 | case BinOpTypeDiv: |
| 210 | 275 | { |
| 211 | 276 | bool is_int = false; |
| ... | ... | @@ -224,11 +289,11 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, |
| 224 | 289 | { |
| 225 | 290 | return ErrorDivByZero; |
| 226 | 291 | } else { |
| 227 | | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_div); |
| 292 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_div, op1_type); |
| 228 | 293 | } |
| 229 | 294 | } |
| 230 | 295 | case BinOpTypeMod: |
| 231 | | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mod); |
| 296 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mod, op1_type); |
| 232 | 297 | case BinOpTypeUnwrapMaybe: |
| 233 | 298 | zig_panic("TODO"); |
| 234 | 299 | case BinOpTypeStrCat: |
| ... | ... | @@ -244,18 +309,61 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) |
| 244 | 309 | |
| 245 | 310 | AstNode *op1 = node->data.bin_op_expr.op1; |
| 246 | 311 | AstNode *op2 = node->data.bin_op_expr.op2; |
| 312 | BinOpType bin_op = node->data.bin_op_expr.bin_op; |
| 313 | |
| 314 | switch (bin_op) { |
| 315 | case BinOpTypeAssign: |
| 316 | case BinOpTypeAssignTimes: |
| 317 | case BinOpTypeAssignDiv: |
| 318 | case BinOpTypeAssignMod: |
| 319 | case BinOpTypeAssignPlus: |
| 320 | case BinOpTypeAssignMinus: |
| 321 | case BinOpTypeAssignBitShiftLeft: |
| 322 | case BinOpTypeAssignBitShiftRight: |
| 323 | case BinOpTypeAssignBitAnd: |
| 324 | case BinOpTypeAssignBitXor: |
| 325 | case BinOpTypeAssignBitOr: |
| 326 | case BinOpTypeAssignBoolAnd: |
| 327 | case BinOpTypeAssignBoolOr: |
| 328 | zig_panic("TODO"); |
| 329 | case BinOpTypeBoolOr: |
| 330 | case BinOpTypeBoolAnd: |
| 331 | case BinOpTypeCmpEq: |
| 332 | case BinOpTypeCmpNotEq: |
| 333 | case BinOpTypeCmpLessThan: |
| 334 | case BinOpTypeCmpGreaterThan: |
| 335 | case BinOpTypeCmpLessOrEq: |
| 336 | case BinOpTypeCmpGreaterOrEq: |
| 337 | case BinOpTypeBinOr: |
| 338 | case BinOpTypeBinXor: |
| 339 | case BinOpTypeBinAnd: |
| 340 | case BinOpTypeBitShiftLeft: |
| 341 | case BinOpTypeBitShiftRight: |
| 342 | case BinOpTypeAdd: |
| 343 | case BinOpTypeSub: |
| 344 | case BinOpTypeMult: |
| 345 | case BinOpTypeDiv: |
| 346 | case BinOpTypeMod: |
| 347 | case BinOpTypeUnwrapMaybe: |
| 348 | case BinOpTypeStrCat: |
| 349 | case BinOpTypeArrayMult: |
| 350 | break; |
| 351 | case BinOpTypeInvalid: |
| 352 | zig_unreachable(); |
| 353 | } |
| 247 | 354 | |
| 248 | 355 | TypeTableEntry *op1_type = get_resolved_expr(op1)->type_entry; |
| 249 | 356 | TypeTableEntry *op2_type = get_resolved_expr(op2)->type_entry; |
| 250 | 357 | |
| 358 | assert(op1_type); |
| 359 | assert(op2_type); |
| 360 | |
| 251 | 361 | ConstExprValue op1_val = {0}; |
| 252 | 362 | if (eval_expr(ef, op1, &op1_val)) return true; |
| 253 | 363 | |
| 254 | 364 | ConstExprValue op2_val = {0}; |
| 255 | 365 | if (eval_expr(ef, op2, &op2_val)) return true; |
| 256 | 366 | |
| 257 | | BinOpType bin_op = node->data.bin_op_expr.bin_op; |
| 258 | | |
| 259 | 367 | int err; |
| 260 | 368 | if ((err = eval_const_expr_bin_op(&op1_val, op1_type, bin_op, &op2_val, op2_type, out_val))) { |
| 261 | 369 | ef->root->abort = true; |
| ... | ... | @@ -568,48 +676,15 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue * |
| 568 | 676 | const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry); |
| 569 | 677 | if (is_max) { |
| 570 | 678 | if (type_entry->data.integral.is_signed) { |
| 571 | | int64_t val; |
| 572 | | if (type_entry->data.integral.bit_count == 64) { |
| 573 | | val = INT64_MAX; |
| 574 | | } else if (type_entry->data.integral.bit_count == 32) { |
| 575 | | val = INT32_MAX; |
| 576 | | } else if (type_entry->data.integral.bit_count == 16) { |
| 577 | | val = INT16_MAX; |
| 578 | | } else if (type_entry->data.integral.bit_count == 8) { |
| 579 | | val = INT8_MAX; |
| 580 | | } else { |
| 581 | | zig_unreachable(); |
| 582 | | } |
| 679 | int64_t val = max_signed_val(type_entry); |
| 583 | 680 | bignum_init_signed(&const_val->data.x_bignum, val); |
| 584 | 681 | } else { |
| 585 | | uint64_t val; |
| 586 | | if (type_entry->data.integral.bit_count == 64) { |
| 587 | | val = UINT64_MAX; |
| 588 | | } else if (type_entry->data.integral.bit_count == 32) { |
| 589 | | val = UINT32_MAX; |
| 590 | | } else if (type_entry->data.integral.bit_count == 16) { |
| 591 | | val = UINT16_MAX; |
| 592 | | } else if (type_entry->data.integral.bit_count == 8) { |
| 593 | | val = UINT8_MAX; |
| 594 | | } else { |
| 595 | | zig_unreachable(); |
| 596 | | } |
| 682 | uint64_t val = max_unsigned_val(type_entry); |
| 597 | 683 | bignum_init_unsigned(&const_val->data.x_bignum, val); |
| 598 | 684 | } |
| 599 | 685 | } else { |
| 600 | 686 | if (type_entry->data.integral.is_signed) { |
| 601 | | int64_t val; |
| 602 | | if (type_entry->data.integral.bit_count == 64) { |
| 603 | | val = INT64_MIN; |
| 604 | | } else if (type_entry->data.integral.bit_count == 32) { |
| 605 | | val = INT32_MIN; |
| 606 | | } else if (type_entry->data.integral.bit_count == 16) { |
| 607 | | val = INT16_MIN; |
| 608 | | } else if (type_entry->data.integral.bit_count == 8) { |
| 609 | | val = INT8_MIN; |
| 610 | | } else { |
| 611 | | zig_unreachable(); |
| 612 | | } |
| 687 | int64_t val = min_signed_val(type_entry); |
| 613 | 688 | bignum_init_signed(&const_val->data.x_bignum, val); |
| 614 | 689 | } else { |
| 615 | 690 | bignum_init_unsigned(&const_val->data.x_bignum, 0); |
| ... | ... | @@ -687,6 +762,8 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_ |
| 687 | 762 | return eval_fn_with_overflow(ef, node, out_val, bignum_add); |
| 688 | 763 | case BuiltinFnIdSubWithOverflow: |
| 689 | 764 | return eval_fn_with_overflow(ef, node, out_val, bignum_sub); |
| 765 | case BuiltinFnIdShlWithOverflow: |
| 766 | return eval_fn_with_overflow(ef, node, out_val, bignum_shl); |
| 690 | 767 | case BuiltinFnIdFence: |
| 691 | 768 | return false; |
| 692 | 769 | case BuiltinFnIdMemcpy: |
| ... | ... | @@ -707,7 +784,6 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_ |
| 707 | 784 | case BuiltinFnIdErrName: |
| 708 | 785 | case BuiltinFnIdEmbedFile: |
| 709 | 786 | case BuiltinFnIdCmpExchange: |
| 710 | | case BuiltinFnIdShlWithOverflow: |
| 711 | 787 | zig_panic("TODO"); |
| 712 | 788 | case BuiltinFnIdBreakpoint: |
| 713 | 789 | case BuiltinFnIdInvalid: |
| ... | ... | @@ -962,8 +1038,31 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v |
| 962 | 1038 | out_val->ok = true; |
| 963 | 1039 | break; |
| 964 | 1040 | } |
| 965 | | case PrefixOpBinNot: |
| 966 | 1041 | case PrefixOpNegation: |
| 1042 | if (expr_type->id == TypeTableEntryIdInt) { |
| 1043 | assert(expr_type->data.integral.is_signed); |
| 1044 | bignum_negate(&out_val->data.x_bignum, &expr_val.data.x_bignum); |
| 1045 | out_val->ok = true; |
| 1046 | bool overflow = !bignum_fits_in_bits(&out_val->data.x_bignum, |
| 1047 | expr_type->data.integral.bit_count, expr_type->data.integral.is_signed); |
| 1048 | if (expr_type->data.integral.is_wrapping) { |
| 1049 | if (overflow) { |
| 1050 | out_val->data.x_bignum.is_negative = true; |
| 1051 | } |
| 1052 | } else if (overflow) { |
| 1053 | ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node, |
| 1054 | buf_sprintf("function evaluation caused overflow")); |
| 1055 | add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here")); |
| 1056 | add_error_note(ef->root->codegen, msg, node, buf_sprintf("overflow occurred here")); |
| 1057 | return true; |
| 1058 | } |
| 1059 | } else if (expr_type->id == TypeTableEntryIdFloat) { |
| 1060 | zig_panic("TODO"); |
| 1061 | } else { |
| 1062 | zig_unreachable(); |
| 1063 | } |
| 1064 | break; |
| 1065 | case PrefixOpBinNot: |
| 967 | 1066 | case PrefixOpMaybe: |
| 968 | 1067 | case PrefixOpError: |
| 969 | 1068 | case PrefixOpUnwrapError: |