Skip to content

Fix Memory64Lowering table.grow and table.copy handling#8311

Closed
sumleo wants to merge 1 commit intoWebAssembly:mainfrom
sumleo:fix-memory64-table-lowering
Closed

Fix Memory64Lowering table.grow and table.copy handling#8311
sumleo wants to merge 1 commit intoWebAssembly:mainfrom
sumleo:fix-memory64-table-lowering

Conversation

@sumleo
Copy link
Contributor

@sumleo sumleo commented Feb 12, 2026

Summary

Two bugs in the table64 lowering within Memory64Lowering:

1. table.grow return value doesn't handle -1 failure

visitTableGrow uses a plain i64.extend_i32_u on the table.grow return value. But table.grow returns -1 (i32) on failure, and i64.extend_i32_u(0xFFFFFFFF) produces 0x00000000FFFFFFFF (4294967295), not i64 -1 (0xFFFFFFFFFFFFFFFF). Code checking result == -1 would fail to detect the failure.

The analogous visitMemoryGrow already has the correct handling: it uses a local.tee + if/else to check for -1 and return i64.const -1 explicitly.

Fix: Apply the same if/else -1 check pattern from visitMemoryGrow to visitTableGrow.

2. table.copy size wrapping uses wrong table check

visitTableCopy wraps curr->size using curr->destTable, but the wasm spec (and child-typer.h) defines the size type as i64 only when both source and dest tables are 64-bit. When copying between a 64-bit and a 32-bit table, the size is i32, but wrapping checks only the dest table — causing an assertion failure (assert(ptr->type == Type::i64)) when dest is 64-bit but source is 32-bit.

Fix: Check both tables before wrapping the size operand.

Test plan

  • Updated existing memory64-lowering.wast test expectations for the new table.grow output
  • New lit test memory64-lowering-table-fixes.wast covering:
    • table.grow with proper -1 if/else handling
    • table.copy from 64-bit to 32-bit table (size stays i32)
    • table.copy from 32-bit to 64-bit table (size stays i32)
    • table.copy between two 64-bit tables (all operands wrapped)
  • All 309 unit tests pass

Two bugs in the table64 lowering:

1. visitTableGrow used a plain i64.extend_i32_u on the return value,
   but table.grow returns -1 on failure. ExtendUInt32 on i32(-1)
   produces i64(4294967295), not i64(-1). Add the same if/else -1
   check pattern already used by visitMemoryGrow.

2. visitTableCopy wrapped curr->size using only the dest table's
   type, but the size operand is i64 only when both source and dest
   tables are 64-bit. When tables have mixed types, wrapping an i32
   size as if it were i64 causes an assertion failure. Check both
   tables before wrapping.
@kripken
Copy link
Member

kripken commented Feb 12, 2026

These fixes look separate, even if they are on the same pass? Please submit separate PRs for them.

@sumleo
Copy link
Contributor Author

sumleo commented Feb 12, 2026

Split into separate PRs per review feedback: #8318 (table.grow) and #8319 (table.copy).

@sumleo sumleo closed this Feb 12, 2026
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