From 38c0126e2777da4a6620d17bf149e80a90521d78 Mon Sep 17 00:00:00 2001 From: Davide Bettio Date: Tue, 8 Jul 2025 23:40:19 +0200 Subject: [PATCH] BIFs: bnot: add support to boxed integers bnot was missing support to boxed integers, so it wasn't supporting integers > 28 bits on 32 bit systems, and > 60 bits on 64 bit systems. Signed-off-by: Davide Bettio --- CHANGELOG.md | 4 +++ src/libAtomVM/bif.c | 60 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ddca7cda..7f475ee02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.6.7] - Unreleased +### Fixed + +- bnot not supports 64-bit integers + ## [0.6.6] - 2025-06-23 ### Added diff --git a/src/libAtomVM/bif.c b/src/libAtomVM/bif.c index e1608e3be..7c63afece 100644 --- a/src/libAtomVM/bif.c +++ b/src/libAtomVM/bif.c @@ -1372,6 +1372,64 @@ term bif_erlang_bsr_2(Context *ctx, uint32_t fail_label, int live, term arg1, te return bitshift_helper(ctx, fail_label, live, arg1, arg2, bsr); } +static term bnot_boxed_helper(Context *ctx, uint32_t fail_label, uint32_t live, term arg1) +{ + if (term_is_boxed_integer(arg1)) { + switch (term_boxed_size(arg1)) { + case 0: + //BUG + AVM_ABORT(); + + case 1: { + avm_int_t val = term_unbox_int(arg1); + if (val >= 0) { + return arg1; + } + + if (val == AVM_INT_MIN) { + #if BOXED_TERMS_REQUIRED_FOR_INT64 == 2 + return make_boxed_int64(ctx, fail_label, live, -((avm_int64_t) val)); + + #elif BOXED_TERMS_REQUIRED_FOR_INT64 == 1 + TRACE("overflow: val: " AVM_INT_FMT "\n", val); + RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM); + + #else + #error "Unsupported configuration." + #endif + + } else { + return make_boxed_int(ctx, fail_label, live, -val); + } + } + + #if BOXED_TERMS_REQUIRED_FOR_INT64 == 2 + case 2: { + avm_int64_t val = term_unbox_int64(arg1); + if (val >= 0) { + return arg1; + } + + if (val == INT64_MIN) { + TRACE("overflow: val:" AVM_INT64_FMT "\n", val); + RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM); + + } else { + return make_boxed_int64(ctx, fail_label, live, -val); + } + } + #endif + default: + RAISE_ERROR_BIF(fail_label, OVERFLOW_ATOM); + } + } else { + TRACE("error: arg1: 0x%lx\n", arg1); + RAISE_ERROR_BIF(fail_label, BADARG_ATOM); + } +} + + + term bif_erlang_bnot_1(Context *ctx, uint32_t fail_label, int live, term arg1) { UNUSED(live); @@ -1380,7 +1438,7 @@ term bif_erlang_bnot_1(Context *ctx, uint32_t fail_label, int live, term arg1) return ~arg1 | TERM_INTEGER_TAG; } else { - RAISE_ERROR_BIF(fail_label, BADARITH_ATOM); + return bnot_boxed_helper(ctx, fail_label, live, arg1); } }