|
57 | 57 | RAISE_ERROR_BIF(fail_label, BADARG_ATOM); \
|
58 | 58 | }
|
59 | 59 |
|
| 60 | +#define MAX(a, b) ((a) > (b) ? (a) : (b)) |
| 61 | + |
60 | 62 | const struct ExportedFunction *bif_registry_get_handler(AtomString module, AtomString function, int arity)
|
61 | 63 | {
|
62 | 64 | char bifname[MAX_BIF_NAME_LEN];
|
@@ -641,84 +643,68 @@ static term mul_overflow_helper(Context *ctx, uint32_t fail_label, uint32_t live
|
641 | 643 |
|
642 | 644 | static term mul_boxed_helper(Context *ctx, uint32_t fail_label, uint32_t live, term arg1, term arg2)
|
643 | 645 | {
|
644 |
| - int use_float = 0; |
645 |
| - int size = 0; |
646 |
| - if (term_is_boxed_integer(arg1)) { |
647 |
| - size = term_boxed_size(arg1); |
648 |
| - } else if (term_is_float(arg1)) { |
649 |
| - use_float = 1; |
650 |
| - } else if (!term_is_integer(arg1)) { |
651 |
| - TRACE("error: arg1: 0x%lx, arg2: 0x%lx\n", arg1, arg2); |
652 |
| - RAISE_ERROR_BIF(fail_label, BADARITH_ATOM); |
653 |
| - } |
654 |
| - |
655 |
| - if (term_is_boxed_integer(arg2)) { |
656 |
| - size |= term_boxed_size(arg2); |
657 |
| - } else if (term_is_float(arg2)) { |
658 |
| - use_float = 1; |
659 |
| - } else if (!term_is_integer(arg2)) { |
660 |
| - TRACE("error: arg1: 0x%lx, arg2: 0x%lx\n", arg1, arg2); |
| 646 | + if (UNLIKELY(!term_is_number(arg1) || !term_is_number(arg2))) { |
661 | 647 | RAISE_ERROR_BIF(fail_label, BADARITH_ATOM);
|
662 | 648 | }
|
663 | 649 |
|
664 |
| - if (use_float) { |
665 |
| - avm_float_t farg1 = term_conv_to_float(arg1); |
666 |
| - avm_float_t farg2 = term_conv_to_float(arg2); |
667 |
| - avm_float_t fresult = farg1 * farg2; |
668 |
| - if (UNLIKELY(!isfinite(fresult))) { |
669 |
| - RAISE_ERROR_BIF(fail_label, BADARITH_ATOM); |
670 |
| - } |
671 |
| - if (UNLIKELY(memory_ensure_free_with_roots(ctx, FLOAT_SIZE, live, ctx->x, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { |
672 |
| - RAISE_ERROR_BIF(fail_label, OUT_OF_MEMORY_ATOM); |
673 |
| - } |
674 |
| - return term_from_float(fresult, &ctx->heap); |
675 |
| - } |
| 650 | + if (term_is_any_integer(arg1) && term_is_any_integer(arg2)) { |
676 | 651 |
|
677 |
| - switch (size) { |
678 |
| - case 0: { |
679 |
| - //BUG |
680 |
| - AVM_ABORT(); |
681 |
| - } |
| 652 | + size_t arg1_size = term_is_integer(arg1) ? 0 : term_boxed_size(arg1); |
| 653 | + size_t arg2_size = term_is_integer(arg2) ? 0 : term_boxed_size(arg2); |
| 654 | + switch (MAX(arg1_size, arg2_size)) { |
| 655 | + case 0: |
| 656 | + UNREACHABLE(); |
| 657 | + case 1: { |
| 658 | + avm_int_t val1 = term_maybe_unbox_int(arg1); |
| 659 | + avm_int_t val2 = term_maybe_unbox_int(arg2); |
| 660 | + avm_int_t res; |
682 | 661 |
|
683 |
| - case 1: { |
684 |
| - avm_int_t val1 = term_maybe_unbox_int(arg1); |
685 |
| - avm_int_t val2 = term_maybe_unbox_int(arg2); |
686 |
| - avm_int_t res; |
| 662 | + if (BUILTIN_MUL_OVERFLOW_INT(val1, val2, &res)) { |
| 663 | + #if BOXED_TERMS_REQUIRED_FOR_INT64 == 2 |
| 664 | + avm_int64_t res64 = (avm_int64_t) val1 * (avm_int64_t) val2; |
| 665 | + return make_boxed_int64(ctx, fail_label, live, res64); |
687 | 666 |
|
688 |
| - if (BUILTIN_MUL_OVERFLOW_INT(val1, val2, &res)) { |
689 |
| - #if BOXED_TERMS_REQUIRED_FOR_INT64 == 2 |
690 |
| - avm_int64_t res64 = (avm_int64_t) val1 * (avm_int64_t) val2; |
691 |
| - return make_boxed_int64(ctx, fail_label, live, res64); |
| 667 | + #elif BOXED_TERMS_REQUIRED_FOR_INT64 == 1 |
| 668 | + TRACE("overflow: arg1: " AVM_INT64_FMT ", arg2: " AVM_INT64_FMT "\n", arg1, arg2); |
| 669 | + RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM); |
| 670 | + #else |
| 671 | + #error "Unsupported configuration." |
| 672 | + #endif |
| 673 | + } |
692 | 674 |
|
693 |
| - #elif BOXED_TERMS_REQUIRED_FOR_INT64 == 1 |
694 |
| - TRACE("overflow: arg1: " AVM_INT64_FMT ", arg2: " AVM_INT64_FMT "\n", arg1, arg2); |
695 |
| - RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM); |
696 |
| - #else |
697 |
| - #error "Unsupported configuration." |
698 |
| - #endif |
| 675 | + return make_maybe_boxed_int(ctx, fail_label, live, res); |
699 | 676 | }
|
700 | 677 |
|
701 |
| - return make_maybe_boxed_int(ctx, fail_label, live, res); |
702 |
| - } |
| 678 | + #if BOXED_TERMS_REQUIRED_FOR_INT64 == 2 |
| 679 | + case 2: { |
| 680 | + avm_int64_t val1 = term_maybe_unbox_int64(arg1); |
| 681 | + avm_int64_t val2 = term_maybe_unbox_int64(arg2); |
| 682 | + avm_int64_t res; |
703 | 683 |
|
704 |
| - #if BOXED_TERMS_REQUIRED_FOR_INT64 == 2 |
705 |
| - case 2: |
706 |
| - case 3: { |
707 |
| - avm_int64_t val1 = term_maybe_unbox_int64(arg1); |
708 |
| - avm_int64_t val2 = term_maybe_unbox_int64(arg2); |
709 |
| - avm_int64_t res; |
| 684 | + if (BUILTIN_MUL_OVERFLOW_INT64(val1, val2, &res)) { |
| 685 | + TRACE("overflow: arg1: 0x%lx, arg2: 0x%lx\n", arg1, arg2); |
| 686 | + RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM); |
| 687 | + } |
710 | 688 |
|
711 |
| - if (BUILTIN_MUL_OVERFLOW_INT64(val1, val2, &res)) { |
712 |
| - TRACE("overflow: arg1: 0x%lx, arg2: 0x%lx\n", arg1, arg2); |
713 |
| - RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM); |
| 689 | + return make_maybe_boxed_int64(ctx, fail_label, live, res); |
714 | 690 | }
|
| 691 | + #endif |
715 | 692 |
|
716 |
| - return make_maybe_boxed_int64(ctx, fail_label, live, res); |
| 693 | + default: |
| 694 | + UNREACHABLE(); |
717 | 695 | }
|
718 |
| - #endif |
719 |
| - |
720 |
| - default: |
721 |
| - RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM); |
| 696 | + } else { |
| 697 | + avm_float_t farg1 = term_conv_to_float(arg1); |
| 698 | + avm_float_t farg2 = term_conv_to_float(arg2); |
| 699 | + avm_float_t fresult = farg1 * farg2; |
| 700 | + if (UNLIKELY(!isfinite(fresult))) { |
| 701 | + RAISE_ERROR_BIF(fail_label, BADARITH_ATOM); |
| 702 | + } |
| 703 | + if (UNLIKELY(memory_ensure_free_with_roots(ctx, FLOAT_SIZE, live, ctx->x, MEMORY_CAN_SHRINK) |
| 704 | + != MEMORY_GC_OK)) { |
| 705 | + RAISE_ERROR_BIF(fail_label, OUT_OF_MEMORY_ATOM); |
| 706 | + } |
| 707 | + return term_from_float(fresult, &ctx->heap); |
722 | 708 | }
|
723 | 709 | }
|
724 | 710 |
|
|
0 commit comments