Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,12 @@ jobs:
cmake_opts_other: "-DAVM_DISABLE_JIT=OFF"
jit_target_arch: "x86_64"

# JIT build with OTP-29.0-rc1
# JIT build with OTP-29.0
- os: "ubuntu-24.04"
cc: "cc"
cxx: "c++"
cflags: ""
otp: "29.0-rc1"
otp: "29.0"
version_type: "strict"
elixir_version: "1.19.5"
rebar3_version: "3.27.0"
Expand Down
64 changes: 46 additions & 18 deletions src/libAtomVM/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,13 @@
#include <zlib.h>
#endif

// BEAM Types version from OTP source code:
// lib/compiler/src/beam_types.hrl
#define BEAM_TYPES_VERSION_V3 3
#define BEAM_TYPES_VERSION_V4 4

// BEAM Type constants from OTP source code:
// /opt/src/otp/lib/compiler/src/beam_types.erl lines 1446-1461
// lib/compiler/src/beam_types.erl
#define BEAM_TYPE_ATOM (1 << 0)
#define BEAM_TYPE_BITSTRING (1 << 1)
#define BEAM_TYPE_CONS (1 << 2)
Expand All @@ -67,14 +72,18 @@
#define BEAM_TYPE_PORT (1 << 9)
#define BEAM_TYPE_REFERENCE (1 << 10)
#define BEAM_TYPE_TUPLE (1 << 11)

#define BEAM_TYPE_HAS_LOWER_BOUND (1 << 12)
#define BEAM_TYPE_HAS_UPPER_BOUND (1 << 13)
#define BEAM_TYPE_HAS_UNIT (1 << 14)

// BEAM Types version from OTP source code:
// /opt/src/otp/lib/compiler/src/beam_types.hrl line 22
#define BEAM_TYPES_VERSION 3
#define BEAM_TYPE_RECORD (1 << 12) // v4 only

// v3 flag bits (OTP 27/28)
#define BEAM_TYPE_V3_HAS_LOWER_BOUND (1 << 12)
#define BEAM_TYPE_V3_HAS_UPPER_BOUND (1 << 13)
#define BEAM_TYPE_V3_HAS_UNIT (1 << 14)
#define BEAM_TYPE_V3_BITS_MASK 0xFFF
// v4 flag bits (OTP 29+)
#define BEAM_TYPE_V4_HAS_LOWER_BOUND (1 << 13)
#define BEAM_TYPE_V4_HAS_UPPER_BOUND (1 << 14)
#define BEAM_TYPE_V4_HAS_UNIT (1 << 15)
#define BEAM_TYPE_V4_BITS_MASK 0x1FFF

#define LITT_UNCOMPRESSED_SIZE_OFFSET 8
#define LITT_HEADER_SIZE 12
Expand Down Expand Up @@ -1411,7 +1420,7 @@ term module_get_type_by_index(const Module *mod, int type_index, Context *ctx)
uint32_t count = READ_32_UNALIGNED(types_data + 4);

// Check if version is supported
if (version != BEAM_TYPES_VERSION) {
if (version != BEAM_TYPES_VERSION_V3 && version != BEAM_TYPES_VERSION_V4) {
return globalcontext_make_atom(ctx->global, ATOM_STR("\x3", "any"));
}

Expand All @@ -1420,6 +1429,22 @@ term module_get_type_by_index(const Module *mod, int type_index, Context *ctx)
return globalcontext_make_atom(ctx->global, ATOM_STR("\x3", "any"));
}

uint16_t has_lower_bound_mask;
uint16_t has_upper_bound_mask;
uint16_t has_unit_mask;
uint16_t type_bits_mask;
if (version == BEAM_TYPES_VERSION_V4) {
has_lower_bound_mask = BEAM_TYPE_V4_HAS_LOWER_BOUND;
has_upper_bound_mask = BEAM_TYPE_V4_HAS_UPPER_BOUND;
has_unit_mask = BEAM_TYPE_V4_HAS_UNIT;
type_bits_mask = BEAM_TYPE_V4_BITS_MASK;
} else {
has_lower_bound_mask = BEAM_TYPE_V3_HAS_LOWER_BOUND;
has_upper_bound_mask = BEAM_TYPE_V3_HAS_UPPER_BOUND;
has_unit_mask = BEAM_TYPE_V3_HAS_UNIT;
type_bits_mask = BEAM_TYPE_V3_BITS_MASK;
}

// Skip to type data
const uint8_t *type_entries = types_data + 8;
const uint8_t *pos = type_entries;
Expand All @@ -1430,13 +1455,13 @@ term module_get_type_by_index(const Module *mod, int type_index, Context *ctx)
pos += 2;

// Skip extra data if present
if (type_bits & BEAM_TYPE_HAS_LOWER_BOUND) {
if (type_bits & has_lower_bound_mask) {
pos += 8;
}
if (type_bits & BEAM_TYPE_HAS_UPPER_BOUND) {
if (type_bits & has_upper_bound_mask) {
pos += 8;
}
if (type_bits & BEAM_TYPE_HAS_UNIT) {
if (type_bits & has_unit_mask) {
pos += 1;
}
}
Expand All @@ -1452,24 +1477,24 @@ term module_get_type_by_index(const Module *mod, int type_index, Context *ctx)
bool has_lower = false;
bool has_upper = false;

if (type_bits & BEAM_TYPE_HAS_LOWER_BOUND) {
if (type_bits & has_lower_bound_mask) {
lower_bound = (int64_t) READ_64_UNALIGNED(pos);
pos += 8;
has_lower = true;
}
if (type_bits & BEAM_TYPE_HAS_UPPER_BOUND) {
if (type_bits & has_upper_bound_mask) {
upper_bound = (int64_t) READ_64_UNALIGNED(pos);
pos += 8;
has_upper = true;
}
if (type_bits & BEAM_TYPE_HAS_UNIT) {
if (type_bits & has_unit_mask) {
unit = *pos + 1; // Stored as unit-1
pos += 1;
}

// Decode type based on TypeBits (matching jit_precompile.erl exact pattern matching)
// From OTP source code: /opt/src/otp/lib/compiler/src/beam_types.erl decode_type function
uint16_t type_pattern = type_bits & 0xFFF; // Mask out flags, keep type bits
// From OTP source code: lib/compiler/src/beam_types.erl decode_type function
uint16_t type_pattern = type_bits & type_bits_mask;

switch (type_pattern) {
case BEAM_TYPE_ATOM:
Expand Down Expand Up @@ -1581,6 +1606,9 @@ term module_get_type_by_index(const Module *mod, int type_index, Context *ctx)
case BEAM_TYPE_TUPLE:
return globalcontext_make_atom(ctx->global, ATOM_STR("\x7", "t_tuple"));

case BEAM_TYPE_RECORD:
return globalcontext_make_atom(ctx->global, ATOM_STR("\x8", "t_record"));

default:
// Default fallback for any other combination or union types
return globalcontext_make_atom(ctx->global, ATOM_STR("\x3", "any"));
Expand Down
Loading