Skip to content

Commit 75d6d2d

Browse files
committed
Forward port changes from v0.6 release branch
Merge `binary_part/3` BIF (PR #1569), fix to `is_number` (#1624) and migration to ubuntu-20.04 container (#1626) from release-0.6 branch.
2 parents d5da7e7 + 65482c8 commit 75d6d2d

File tree

10 files changed

+158
-87
lines changed

10 files changed

+158
-87
lines changed

.github/workflows/build-and-test.yaml

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ concurrency:
3434

3535
jobs:
3636
build-and-test:
37-
runs-on: ${{ matrix.os }}
37+
runs-on: ${{ matrix.os || 'ubuntu-24.04' }}
38+
container: ${{ matrix.container }}
3839
strategy:
3940

4041
fail-fast: false
@@ -57,21 +58,21 @@ jobs:
5758
- cc: "gcc-7"
5859
cxx: "g++-7"
5960
compiler_pkgs: "gcc-7 g++-7"
60-
os: "ubuntu-20.04"
61+
container: "ubuntu:20.04"
6162
otp: "27"
6263
elixir_version: "1.17"
6364
rebar3_version: "3.24.0"
6465
- cc: "gcc-8"
6566
cxx: "g++-8"
6667
compiler_pkgs: "gcc-8 g++-8"
67-
os: "ubuntu-20.04"
68+
container: "ubuntu:20.04"
6869
otp: "27"
6970
elixir_version: "1.17"
7071
rebar3_version: "3.24.0"
7172
- cc: "gcc-9"
7273
cxx: "g++-9"
7374
compiler_pkgs: "gcc-9 g++-9"
74-
os: "ubuntu-20.04"
75+
container: "ubuntu:20.04"
7576
# otp: all
7677
- cc: "gcc-10"
7778
cxx: "g++-10"
@@ -119,13 +120,13 @@ jobs:
119120
cxx: "clang++-10"
120121
compiler_pkgs: "clang-10"
121122
cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON"
122-
os: "ubuntu-20.04"
123+
container: "ubuntu:20.04"
123124
# otp: all
124125
- cc: "clang-11"
125126
cxx: "clang++-11"
126127
compiler_pkgs: "clang-11"
127128
cmake_opts_other: "-DAVM_WARNINGS_ARE_ERRORS=ON"
128-
os: "ubuntu-20.04"
129+
container: "ubuntu:20.04"
129130
otp: "27"
130131
elixir_version: "1.17"
131132
rebar3_version: "3.24.0"
@@ -195,37 +196,41 @@ jobs:
195196
rebar3_version: "3.24.0"
196197

197198
# Old versions of OTP/Elixir
198-
- os: "ubuntu-20.04"
199+
- container: "ubuntu:20.04"
199200
cc: "cc"
200201
cxx: "c++"
201202
cflags: ""
202203
otp: "21"
203204
elixir_version: "1.7"
204205
rebar3_version: "3.15.2"
206+
compiler_pkgs: "g++"
205207

206-
- os: "ubuntu-20.04"
208+
- container: "ubuntu:20.04"
207209
cc: "cc"
208210
cxx: "c++"
209211
cflags: ""
210212
otp: "22"
211213
elixir_version: "1.8"
212214
rebar3_version: "3.18.0"
215+
compiler_pkgs: "g++"
213216

214-
- os: "ubuntu-20.04"
217+
- container: "ubuntu:20.04"
215218
cc: "cc"
216219
cxx: "c++"
217220
cflags: ""
218221
otp: "23"
219222
elixir_version: "1.11"
220223
rebar3_version: "3.20.0"
224+
compiler_pkgs: "g++"
221225

222-
- os: "ubuntu-22.04"
226+
- container: "ubuntu:20.04"
223227
cc: "cc"
224228
cxx: "c++"
225229
cflags: ""
226230
otp: "24"
227231
elixir_version: "1.14"
228232
rebar3_version: "3.23.0"
233+
compiler_pkgs: "g++"
229234

230235
- os: "ubuntu-24.04"
231236
cc: "cc"
@@ -235,13 +240,14 @@ jobs:
235240
rebar3_version: "3.24.0"
236241

237242
# Additional default compiler builds
238-
- os: "ubuntu-20.04"
243+
- container: "ubuntu:20.04"
239244
cc: "cc"
240245
cxx: "c++"
241246
cflags: ""
242247
otp: "27"
243248
elixir_version: "1.17"
244249
rebar3_version: "3.24.0"
250+
compiler_pkgs: "g++"
245251

246252
- os: "ubuntu-22.04"
247253
cc: "cc"
@@ -271,7 +277,7 @@ jobs:
271277
compiler_pkgs: "clang-18"
272278

273279
# Additional 32 bits build
274-
- os: "ubuntu-20.04"
280+
- container: "ubuntu:20.04"
275281
cc: "gcc-10"
276282
cxx: "g++-10"
277283
cflags: "-m32 -O3"
@@ -285,13 +291,30 @@ jobs:
285291
libc6-dbg:i386 zlib1g-dev:i386 libmbedtls-dev:i386"
286292

287293
env:
294+
ImageOS: ${{ matrix.container == 'ubuntu:20.04' && 'ubuntu20' || matrix.os == 'ubuntu-20.04' && 'ubuntu20' || matrix.os == 'ubuntu-22.04' && 'ubuntu22' || matrix.os == 'ubuntu-24.04' && 'ubuntu24' || 'ubuntu24' }}
288295
CC: ${{ matrix.cc }}
289296
CXX: ${{ matrix.cxx }}
290297
CFLAGS: ${{ matrix.cflags }}
291298
CXXFLAGS: ${{ matrix.cflags }}
299+
DEBIAN_FRONTEND: noninteractive
300+
TZ: "Etc/UTC"
292301

293302
steps:
294303
# Setup
304+
- name: "Install deps for containers"
305+
if: matrix.container != ''
306+
run: apt-get update && apt-get install -y --no-install-recommends sudo unzip git tzdata
307+
308+
- name: "Add i386 architecture"
309+
if: matrix.arch == 'i386'
310+
run: sudo dpkg --add-architecture i386
311+
312+
- name: "APT update"
313+
run: sudo apt update -y
314+
315+
- name: "Install deps"
316+
run: sudo apt install -y ${{ matrix.compiler_pkgs}} cmake gperf zlib1g-dev doxygen valgrind libmbedtls-dev
317+
295318
- name: "Checkout repo"
296319
uses: actions/checkout@v4
297320
with:
@@ -308,16 +331,6 @@ jobs:
308331
https://repo.hex.pm
309332
https://cdn.jsdelivr.net/hex
310333
311-
- name: "Add i386 architecture"
312-
if: matrix.arch == 'i386'
313-
run: sudo dpkg --add-architecture i386
314-
315-
- name: "APT update"
316-
run: sudo apt update -y
317-
318-
- name: "Install deps"
319-
run: sudo apt install -y ${{ matrix.compiler_pkgs}} cmake gperf zlib1g-dev doxygen valgrind libmbedtls-dev
320-
321334
# Builder info
322335
- name: "System info"
323336
run: |
@@ -436,10 +449,12 @@ jobs:
436449
working-directory: build
437450
run: |
438451
ulimit -c unlimited
439-
if command -v elixirc &> /dev/null
452+
if command -v elixirc >/dev/null 2>&1 && command -v elixir >/dev/null 2>&1
440453
then
441454
valgrind --error-exitcode=1 ./src/AtomVM ./tests/libs/exavmlib/Tests.avm
442455
./src/AtomVM ./tests/libs/exavmlib/Tests.avm
456+
else
457+
echo "Elixir not installed, skipping Elixir tests"
443458
fi
444459
445460
- name: "Install and smoke test"

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ memory error
9595
- Fix `is_function/2` guard
9696
- Fixed segfault when calling `lists:reverse/1` (#1600)
9797
- Fixed nif_atomvm_posix_read GC bug
98+
- Fixed `erlang:is_number/1` function, now returns true also for floats
9899

99100
### Changed
100101

src/libAtomVM/bif.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,30 @@ term bif_erlang_bit_size_1(Context *ctx, uint32_t fail_label, int live, term arg
112112
return term_from_int32(len);
113113
}
114114

115+
term bif_erlang_binary_part_3(Context *ctx, uint32_t fail_label, int live, term arg1, term arg2, term arg3)
116+
{
117+
VALIDATE_VALUE_BIF(fail_label, arg1, term_is_binary);
118+
VALIDATE_VALUE_BIF(fail_label, arg2, term_is_integer);
119+
VALIDATE_VALUE_BIF(fail_label, arg3, term_is_integer);
120+
121+
avm_int_t pos = term_to_int(arg2);
122+
avm_int_t len = term_to_int(arg3);
123+
BinaryPosLen slice;
124+
if (UNLIKELY(!term_normalize_binary_pos_len(arg1, pos, len, &slice))) {
125+
RAISE_ERROR_BIF(fail_label, BADARG_ATOM);
126+
}
127+
128+
TERM_DEBUG_ASSERT((sizeof(ctx->x) / sizeof(ctx->x[0])) >= MAX_REG + 1);
129+
ctx->x[live] = arg1;
130+
size_t heap_size = term_sub_binary_heap_size(arg1, len);
131+
if (UNLIKELY(memory_ensure_free_with_roots(ctx, heap_size, live + 1, ctx->x, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
132+
RAISE_ERROR_BIF(fail_label, OUT_OF_MEMORY_ATOM);
133+
}
134+
arg1 = ctx->x[live];
135+
136+
return term_maybe_create_sub_binary(arg1, slice.pos, slice.len, &ctx->heap, ctx->global);
137+
}
138+
115139
term bif_erlang_is_atom_1(Context *ctx, uint32_t fail_label, term arg1)
116140
{
117141
UNUSED(ctx);
@@ -217,8 +241,7 @@ term bif_erlang_is_number_1(Context *ctx, uint32_t fail_label, term arg1)
217241
UNUSED(ctx);
218242
UNUSED(fail_label);
219243

220-
//TODO: change to term_is_number
221-
return term_is_any_integer(arg1) ? TRUE_ATOM : FALSE_ATOM;
244+
return term_is_number(arg1) ? TRUE_ATOM : FALSE_ATOM;
222245
}
223246

224247
term bif_erlang_is_pid_1(Context *ctx, uint32_t fail_label, term arg1)

src/libAtomVM/bif.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const struct ExportedFunction *bif_registry_get_handler(AtomString module, AtomS
4444
term bif_erlang_self_0(Context *ctx);
4545
term bif_erlang_byte_size_1(Context *ctx, uint32_t fail_label, int live, term arg1);
4646
term bif_erlang_bit_size_1(Context *ctx, uint32_t fail_label, int live, term arg1);
47+
term bif_erlang_binary_part_3(Context *ctx, uint32_t fail_label, int live, term arg1, term arg2, term arg3);
4748
term bif_erlang_length_1(Context *ctx, uint32_t fail_label, int live, term arg1);
4849

4950
term bif_erlang_is_atom_1(Context *ctx, uint32_t fail_label, term arg1);

src/libAtomVM/bifs.gperf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ erlang:self/0, {.bif.base.type = BIFFunctionType, .bif.bif0_ptr = bif_erlang_sel
3939
erlang:length/1, {.gcbif.base.type = GCBIFFunctionType, .gcbif.gcbif1_ptr = bif_erlang_length_1}
4040
erlang:byte_size/1, {.gcbif.base.type = GCBIFFunctionType, .gcbif.gcbif1_ptr = bif_erlang_byte_size_1}
4141
erlang:bit_size/1, {.gcbif.base.type = GCBIFFunctionType, .gcbif.gcbif1_ptr = bif_erlang_bit_size_1}
42+
erlang:binary_part/3, {.gcbif.base.type = GCBIFFunctionType, .gcbif.gcbif3_ptr = bif_erlang_binary_part_3}
4243
erlang:get/1, {.bif.base.type = BIFFunctionType, .bif.bif1_ptr = bif_erlang_get_1}
4344
erlang:is_atom/1, {.bif.base.type = BIFFunctionType, .bif.bif1_ptr = bif_erlang_is_atom_1}
4445
erlang:is_bitstring/1, {.bif.base.type = BIFFunctionType, .bif.bif1_ptr = bif_erlang_is_binary_1}

src/libAtomVM/nifs.c

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3028,33 +3028,26 @@ static term nif_binary_last_1(Context *ctx, int argc, term argv[])
30283028
static term nif_binary_part_3(Context *ctx, int argc, term argv[])
30293029
{
30303030
UNUSED(argc);
3031-
3032-
term bin_term = argv[0];
3031+
term pattern_term = argv[0];
30333032
term pos_term = argv[1];
30343033
term len_term = argv[2];
3035-
3036-
VALIDATE_VALUE(bin_term, term_is_binary);
3034+
VALIDATE_VALUE(pattern_term, term_is_binary);
30373035
VALIDATE_VALUE(pos_term, term_is_integer);
30383036
VALIDATE_VALUE(len_term, term_is_integer);
30393037

3040-
int bin_size = term_binary_size(bin_term);
30413038
avm_int_t pos = term_to_int(pos_term);
30423039
avm_int_t len = term_to_int(len_term);
3043-
3044-
if (len < 0) {
3045-
pos += len;
3046-
len = -len;
3047-
}
3048-
3049-
if (UNLIKELY((pos < 0) || (pos > bin_size) || (pos + len > bin_size))) {
3040+
BinaryPosLen slice;
3041+
if (UNLIKELY(!term_normalize_binary_pos_len(pattern_term, pos, len, &slice))) {
30503042
RAISE_ERROR(BADARG_ATOM);
30513043
}
30523044

3053-
size_t size = term_sub_binary_heap_size(bin_term, len);
3054-
if (UNLIKELY(memory_ensure_free_with_roots(ctx, size, 1, &bin_term, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
3045+
size_t heap_size = term_sub_binary_heap_size(pattern_term, len);
3046+
if (UNLIKELY(memory_ensure_free_with_roots(ctx, heap_size, 1, &pattern_term, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
30553047
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
30563048
}
3057-
return term_maybe_create_sub_binary(bin_term, pos, len, &ctx->heap, ctx->global);
3049+
3050+
return term_maybe_create_sub_binary(pattern_term, slice.pos, slice.len, &ctx->heap, ctx->global);
30583051
}
30593052

30603053
static term nif_binary_split(Context *ctx, int argc, term argv[])

src/libAtomVM/term.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ struct PrinterFun
136136
printer_function_t print;
137137
};
138138

139+
typedef struct BinaryPosLen
140+
{
141+
avm_int_t pos;
142+
avm_int_t len;
143+
} BinaryPosLen;
144+
139145
enum RefcBinaryFlags
140146
{
141147
RefcNoFlags = 0,
@@ -1106,6 +1112,33 @@ static inline term term_create_empty_binary(size_t size, Heap *heap, GlobalConte
11061112
return t;
11071113
}
11081114

1115+
static inline bool term_normalize_binary_pos_len(term binary, avm_int_t pos, avm_int_t len, BinaryPosLen *pos_len)
1116+
{
1117+
avm_int_t size = (avm_int_t) term_binary_size(binary);
1118+
if (len < 0) {
1119+
pos += len;
1120+
len = -len;
1121+
}
1122+
1123+
if (UNLIKELY((pos < 0) || (pos > size) || (pos + len > size))) {
1124+
return false;
1125+
}
1126+
1127+
pos_len->pos = pos;
1128+
pos_len->len = len;
1129+
return true;
1130+
}
1131+
1132+
static inline bool term_is_invalid_binary_pos_len(BinaryPosLen pos_len)
1133+
{
1134+
return pos_len.pos == -1 && pos_len.len == -1;
1135+
}
1136+
1137+
static inline BinaryPosLen term_invalid_binary_pos_len(void)
1138+
{
1139+
return (BinaryPosLen) { .pos = -1, .len = -1 };
1140+
}
1141+
11091142
/**
11101143
* @brief Insert an binary into a binary (using bit syntax).
11111144
*

tests/erlang_tests/float_is_number.erl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@
2323
-export([start/0, pow/2, test/1, id/1]).
2424

2525
start() ->
26-
Res = (pow(-2, 63) + id(10.0)) * id(-1.0),
26+
Res = ?MODULE:id((pow(-2, 63) + id(10.0)) * id(-1.0)),
27+
true = ?MODULE:id(is_number(Res)),
2728
test(Res).
2829

2930
id(I) when is_float(I) ->
31+
I;
32+
id(I) when is_atom(I) ->
3033
I.
3134

3235
pow(_N, 0) ->

0 commit comments

Comments
 (0)