Skip to content

Conversation

@jgonet
Copy link
Contributor

@jgonet jgonet commented Dec 17, 2025

On wasm32, terms are aligned by 4 bytes. memory_heap_allocation returns a pointer for n terms. We used float_term_t to create an union between a term and float. However, floats are aligned to 8 bytes which made casting between union and term pointers unsafe.

We replaced union usage to memcpy which allows unaligned memory access. The true solution would be to return correctly aligned memory from memory_heap_alloc but fix for that would need a lot more testing.

These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).

SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later

On wasm32, terms are aligned by 4 bytes. `memory_heap_allocation` returns a pointer for `n` terms.
We used float_term_t to create an union between a term and float. However, floats are aligned to 8 bytes which made
casting between union and term pointers unsafe.

We replaced union usage to `memcpy` which allows unaligned memory access. The true solution would be to return
correctly aligned memory from memory_heap_alloc but fix for that would need a lot more testing.

Signed-off-by: Jakub Gonet <jakub.gonet@swmansion.com>
float_term_t *boxed_float = (float_term_t *) (boxed_value + 1);
boxed_float->f = f;

// For wasm32, alignof(avm_float_t) = 8 and alignof(term) = 4
Copy link
Collaborator

@bettio bettio Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is somehow slightly misleading, this is not just an issue for wasm32.
It should be rephrased as:
// alignof(avm_float_t) might be != alignof(term)


// For wasm32, alignof(avm_float_t) = 8 and alignof(term) = 4
// `memory_heap_alloc` returns memory aligned to term size.
memcpy(boxed_value + 1, &f, sizeof(avm_float_t));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, but sadly there is a know ESP32 GCC bug that I opened 2 years ago: https://gcc.gnu.org/pipermail/gcc-bugs/2023-October/839353.html

Can you keep also the old code and use it with such a similar macro?

#if defined(__XTENSA__)
// See https://gcc.gnu.org/pipermail/gcc-bugs/2023-October/839353.html
[...]
#else
// your new code here
#endif

return boxed_float->f;
avm_float_t result;
// see `term_from_float`
memcpy(&result, term_to_const_term_ptr(t) + 1, sizeof(avm_float_t));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the previous comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants