Add support for Hexagon architecture#4933
Open
androm3da wants to merge 11 commits into
Open
Conversation
androm3da
requested review from
TianlongLiang,
lum1n0us,
no1wudi and
yamt
as code owners
May 3, 2026 03:34
androm3da
force-pushed
the
hexagon-upstream-v2
branch
5 times, most recently
from
May 7, 2026 19:41
0ccab07 to
4e6cd5a
Compare
androm3da
force-pushed
the
hexagon-upstream-v2
branch
from
June 3, 2026 19:53
4e6cd5a to
ac35bf8
Compare
Split V128 memory access (LOAD_V128/STORE_V128) into a separate three-way guard independent of the scalar unaligned-access flag, and add a target_supports_unaligned_simd field to AOTCompContext. Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
Add interpreter and AOT execution support for Qualcomm Hexagon DSP: invokeNative trampoline, ELF relocation handler with PLT stubs, wamrc --target=hexagon with auto -small-data, SIMD enablement, and cross-compilation platform cmake. Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
WASMTableInstance contains 64-bit members (the elem_ref_type union), so alignof(WASMTableInstance) == 8, and the compiler may legitimately emit 64-bit stores against it (e.g. merging the adjacent 32-bit cur_size and max_size stores in tables_instantiate). But the table region layout packed each instance at offsetof(elems) + elem_count * 4 bytes on 32-bit targets, so any table with an odd element count left the next instance only 4-byte aligned, and the global data preceding the region could leave even the first one misaligned. On strict-alignment targets (Hexagon) instantiating such a module faults with SIGBUS; elsewhere it is silent undefined behavior. Round each table instance size and the table region start up to 8 bytes in the allocation sizing, first_table derivation, and both tables_instantiate walk loops, which must all stay in sync. Found running the WASM spec suite (call_indirect, multiple-tables module) under qemu-hexagon user-mode with unaligned-access faulting enabled.
Three fast-interp loader paths did raw multi-byte stores to addresses that are not guaranteed naturally aligned, faulting (SIGBUS) on strict-alignment targets such as Hexagon: - The WASM_OP_SELECT / SELECT_128 label fixup wrote the replacement label address with a raw *(uint32 *) / *(int32 *) cast into the compiled-code stream at p_code_compiled_tmp - 4. The stream packs 1- and 2-byte items, so that address can be 2-byte aligned. Use the alignment-safe STORE_U32 helper, matching wasm_loader_emit_uint32. - reserve_block_ret and copy_params_to_dynamic_space carve a uint8 cells[] array and int16 offset arrays out of one allocation with no padding between them, so an odd element count leaves the int16 arrays on odd addresses. Round the cells region up to 2 bytes. Found running the WASM spec suite (left-to-right, block/br/fac/func/if and const) under qemu-hexagon user-mode with unaligned-access faulting enabled.
execute_func marshals wasm arguments into a uint32 cell array, which is only guaranteed 4-byte aligned. The V128 parameter and result paths cast &argv1[p] to uint64* and dereferenced it directly, faulting (SIGBUS) on strict-alignment targets such as Hexagon whenever the V128 lands on a 4-mod-8 cell boundary (e.g. any export taking (i32, v128)). The i64 and f64 paths already store word-by-word through a union; do the same for V128 argument parsing and result printing. Found running the WASM SIMD spec suite (simd_align etc., 21 cases) under qemu-hexagon user-mode with unaligned-access faulting enabled.
The SIMD_v128_const handler read its 16-byte immediate with *(V128 *)orig_ip, but frame_ip points into the compiled code stream, which only guarantees 2-byte alignment. On strict-alignment targets (Hexagon) the resulting 64-bit loads fault with SIGBUS as soon as a function containing v128.const executes (e.g. every *_with_const_* export in the SIMD spec suite). Use LOAD_V128, which is alignment-safe on such targets, like the v128.load handler already does; the v8x16.shuffle handler already copies its immediate with bh_memcpy_s. Found running the WASM SIMD spec suite (simd_const and the *_arith2 suites) under qemu-hexagon user-mode with unaligned-access faulting enabled.
…ayout Commit bc2f45e ("fix(interpreter): keep WASMTableInstance instances 8-byte aligned") padded the table region in wasm_runtime.c (global data rounded up to 8 bytes, each table instance rounded up to 8 bytes) so instances stay naturally aligned for their 64-bit members on strict-alignment targets. But that layout is duplicated in three more places that were not updated: - fast-jit computes table offsets statically in jit_frontend_get_table_inst_offset()/get_first_table_inst_offset(); with the runtime layout shifted by the new padding, any module with global_data_size % 8 != 0 read table slots at stale offsets. Reproduced on x86-64 fast-jit with a module holding one i32 global and a 2-entry funcref table: call_indirect raised "indirect call type mismatch" for element 0 and called the wrong function for element 1. - LLVM-JIT bakes the same offsets into generated code through get_tbl_inst_offset() in aot_emit_table.c, with the same failure mode. - aot_runtime.c still packed AOTTableInstance records with no padding, leaving AOT mode exposed to the same misaligned 64-bit accesses on strict-alignment targets that motivated the interpreter fix. Apply the identical alignment rule in all three places, so the four sites that duplicate this layout (wasm_runtime.c, aot_runtime.c, aot_emit_table.c, jit_frontend.c) agree again. get_tbl_inst_offset() computes the padding from the target's pointer size, so cross-compiled AOT output matches the target runtime's layout. Also fix the pre-existing sizeof(uint32) elem size in jit_frontend's import-table walk, which under-counted the stride of imported tables on 64-bit (elems are table_elem_type_t, i.e. pointer-sized). Note: generated AOT/JIT code and the runtime must come from the same tree, as the in-memory instance layout changed; the AOT file format is unaffected. Verified: the reproducer now passes under fast-jit, host AOT and hexagon AOT (qemu user-mode); full spec suite green in aot mode on hexagon and the layout is a no-op wherever global data size and table strides were already multiples of 8. Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
…ands
Wasm linear-memory addresses can have any alignment -- the memarg
align field is only a hint -- but two interpreter paths dereferenced
them with helpers that require alignment, faulting with SIGBUS on
strict-alignment targets (found on Hexagon under qemu user-mode with
unaligned-access faulting; silent UB elsewhere):
- classic interpreter, plain i64.store/f64.store: wrote through
PUT_I64_TO_ADDR, which performs two 32-bit stores and is only meant
for the 4-byte-aligned operand stack. memory.wast ("cast" performs
i64.store align=1 at address 9), float_memory.wast and
call_indirect.wast all crashed. Switch to the alignment-safe
STORE_I64. This was the only remaining unsafe linear-memory access
in wasm_interp_classic.c (all other maddr uses already go through
LOAD_*/STORE_*).
- fast interpreter, SIMD lane/zero loads and lane stores:
SIMD_LOAD_LANE_COMMON (shared by v128.loadN_lane and v128.loadN_zero)
read 16/32-bit lanes with direct dereferences and 64-bit lanes with
the stack-only GET_I64_FROM_ADDR; SIMD_STORE_LANE_OP wrote 16/32-bit
lanes directly. simd_load16/32/64_lane, simd_load_zero and
simd_store16/32_lane crashed, while simd_store64_lane -- already
using STORE_I64 -- passed, confirming the diagnosis. Switch to
LOAD_U16/LOAD_U32/LOAD_I64 and STORE_U16/STORE_U32.
On targets with WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS the helpers
compile to the same direct accesses as before, so this is a no-op
there (re-verified on x86-64).
With these fixes the memory, call_indirect, float_memory and all nine
simd lane/zero spec suites pass on Hexagon in both interpreters.
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
The CLI argument parser trusted the bit pattern strtof/strtod return
for NaN inputs, only patching in the sign for a leading '-' and an
explicit payload after ':'. That breaks on platforms whose libc does
not return the canonical quiet NaN: musl on Hexagon returns the
hardware default NaN 0xffffffff from strtof("nan") -- negative sign,
all-ones payload -- because the parsed double is narrowed by a convert
instruction that canonicalizes NaNs. Any spec assert passing a
positive NaN argument to a sign-sensitive op then failed, e.g.
(assert_return (invoke "copysign" (f32.const -0x1p-149)
(f32.const nan))
(f32.const 0x1p-149))
returned -0x1p-149 because the "nan" argument arrived negative.
An MSVC-only workaround for the same class of problem (strtof
returning a non-canonical payload) already existed; make it
unconditional: on isnan, reset the value to nanf("")/nan("")
(0x7fc00000 / 0x7ff8000000000000) before applying the requested sign
and payload. On glibc this is a behavioral no-op since strtof("nan")
already returns exactly that value.
Fixes the f32_bitwise and conversions spec suites on Hexagon; they are
removed from the skip list in the follow-up test-script commit.
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
The spec-test workflow built a single iwasm (the product-mini defaults: fast-interp with SIMD) and ran it for every matrix cell, so the classic-interp cells never actually exercised the classic interpreter -- and SIMD + classic-interp is not a supported build combination in the first place. Build two artifacts instead (fast-interp+SIMD, and classic-interp with -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_SIMD=0), download the right one per running mode, and exclude the SIMD x classic-interp cell with a comment. The aot cell keeps the fast-interp binary; both builds have AOT support and the interpreter kind does not matter there. Update the hexagon skip list in all.py to match verified reality (fast-interp, classic-interp and aot all green under qemu-hexagon user-mode with these skips): - drop f32_bitwise and conversions: they pass after the NaN CLI-argument normalization in wasm_application.c. - float_exprs: keep, now attributed correctly -- Hexagon FP arithmetic produces the default NaN (all-ones payload) rather than the wasm-canonical quiet NaN, so the *_nan_bitpattern checks fail (same class as the x87 skip for i386). - simd pmin/pmax: keep, now attributed correctly -- clang's Hexagon backend lowers the strict-IEEE "(b < a) ? b : a" pattern to sfmin/sfmax (minNum NaN semantics) without nnan, so lanes with a NaN first operand come back wrong. - simd_lane / simd_splat: keep -- musl (LD64) strtod parses long hex-float CLI arguments 1 ulp low (e.g. 0x0123456789ABCDEFabcdef); a test-harness artifact, not an engine bug. - i32 / i64: keep skipped for the clang rotl/rotr miscompile (fixed by llvm-project 006429da6ab9); re-enabling needs the fix in BOTH the Hexagon cross toolchain that builds iwasm (interp modes pass with a fixed 22.1.8 build) AND the LLVM wamrc links (aot fails with any unfixed LLVM, observed from 18.1.x through 22.x). Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
androm3da
force-pushed
the
hexagon-upstream-v2
branch
from
July 16, 2026 21:39
ac35bf8 to
fa8dfe5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.