Skip to content

Commit

Permalink
Fix byte order for big-endian platforms (#4015)
Browse files Browse the repository at this point in the history
Co-authored-by: daxpedda <daxpedda@gmail.com>
  • Loading branch information
magic-akari and daxpedda authored Jul 29, 2024
1 parent 7f3c21b commit a2761f6
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 96 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@
* Fix `no_std` support and therefor compiling with `default-features = false`.
[#4005](https://github.com/rustwasm/wasm-bindgen/pull/4005)

* Fix byte order for big-endian platforms.
[#4015](https://github.com/rustwasm/wasm-bindgen/pull/4015)

--------------------------------------------------------------------------------

## [0.2.92](https://github.com/rustwasm/wasm-bindgen/compare/0.2.91...0.2.92)
Expand Down
30 changes: 18 additions & 12 deletions crates/cli-support/src/js/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,19 +784,21 @@ fn instruction(
}

Instruction::StoreRetptr { ty, offset, mem } => {
let (mem, size) = match ty {
AdapterType::I32 => (js.cx.expose_int32_memory(*mem), 4),
AdapterType::I64 => (js.cx.expose_int64_memory(*mem), 8),
AdapterType::F32 => (js.cx.expose_f32_memory(*mem), 4),
AdapterType::F64 => (js.cx.expose_f64_memory(*mem), 8),
let mem = js.cx.expose_dataview_memory(*mem);
let (method, size) = match ty {
AdapterType::I32 => ("setInt32", 4),
AdapterType::I64 => ("setBigInt64", 8),
AdapterType::F32 => ("setFloat32", 4),
AdapterType::F64 => ("setFloat64", 8),
other => bail!("invalid aggregate return type {:?}", other),
};
// Note that we always assume the return pointer is argument 0,
// which is currently the case for LLVM.
let val = js.pop();
let expr = format!(
"{}()[{} / {} + {}] = {};",
"{}().{}({} + {} * {}, {}, true);",
mem,
method,
js.arg(0),
size,
offset,
Expand All @@ -806,11 +808,12 @@ fn instruction(
}

Instruction::LoadRetptr { ty, offset, mem } => {
let (mem, quads) = match ty {
AdapterType::I32 => (js.cx.expose_int32_memory(*mem), 1),
AdapterType::I64 => (js.cx.expose_int64_memory(*mem), 2),
AdapterType::F32 => (js.cx.expose_f32_memory(*mem), 1),
AdapterType::F64 => (js.cx.expose_f64_memory(*mem), 2),
let mem = js.cx.expose_dataview_memory(*mem);
let (method, quads) = match ty {
AdapterType::I32 => ("getInt32", 1),
AdapterType::I64 => ("getBigInt64", 2),
AdapterType::F32 => ("getFloat32", 1),
AdapterType::F64 => ("getFloat64", 2),
other => bail!("invalid aggregate return type {:?}", other),
};
let size = quads * 4;
Expand All @@ -820,7 +823,10 @@ fn instruction(
// If we're loading from the return pointer then we must have pushed
// it earlier, and we always push the same value, so load that value
// here
let expr = format!("{}()[retptr / {} + {}]", mem, size, scaled_offset);
let expr = format!(
"{}().{}(retptr + {} * {}, true)",
mem, method, size, scaled_offset
);
js.prelude(&format!("var r{} = {};", offset, expr));
js.push(format!("r{}", offset));
}
Expand Down
50 changes: 28 additions & 22 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1392,7 +1392,7 @@ impl<'a> Context<'a> {
}

fn expose_pass_array_jsvalue_to_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
let mem = self.expose_uint32_memory(memory);
let mem = self.expose_dataview_memory(memory);
let ret = MemView {
name: "passArrayJsValueToWasm".into(),
num: mem.num,
Expand All @@ -1412,7 +1412,7 @@ impl<'a> Context<'a> {
const ptr = malloc(array.length * 4, 4) >>> 0;
const mem = {}();
for (let i = 0; i < array.length; i++) {{
mem[ptr / 4 + i] = {}(array[i]);
mem.setUint32(ptr + 4 * i, {}(array[i]), true);
}}
WASM_VECTOR_LEN = array.length;
return ptr;
Expand All @@ -1429,7 +1429,7 @@ impl<'a> Context<'a> {
const ptr = malloc(array.length * 4, 4) >>> 0;
const mem = {}();
for (let i = 0; i < array.length; i++) {{
mem[ptr / 4 + i] = addHeapObject(array[i]);
mem.setUint32(ptr + 4 * i, addHeapObject(array[i]), true);
}}
WASM_VECTOR_LEN = array.length;
return ptr;
Expand Down Expand Up @@ -1639,7 +1639,7 @@ impl<'a> Context<'a> {
}

fn expose_get_array_js_value_from_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
let mem = self.expose_uint32_memory(memory);
let mem = self.expose_dataview_memory(memory);
let ret = MemView {
name: "getArrayJsValueFromWasm".into(),
num: mem.num,
Expand All @@ -1656,10 +1656,9 @@ impl<'a> Context<'a> {
function {}(ptr, len) {{
ptr = ptr >>> 0;
const mem = {}();
const slice = mem.subarray(ptr / 4, ptr / 4 + len);
const result = [];
for (let i = 0; i < slice.length; i++) {{
result.push(wasm.{}.get(slice[i]));
for (let i = ptr; i < ptr + 4 * len; i += 4) {{
result.push(wasm.{}.get(mem.getUint32(i, true)));
}}
wasm.{}(ptr, len);
return result;
Expand All @@ -1675,10 +1674,9 @@ impl<'a> Context<'a> {
function {}(ptr, len) {{
ptr = ptr >>> 0;
const mem = {}();
const slice = mem.subarray(ptr / 4, ptr / 4 + len);
const result = [];
for (let i = 0; i < slice.length; i++) {{
result.push(takeObject(slice[i]));
for (let i = ptr; i < ptr + 4 * len; i += 4) {{
result.push(takeObject(mem.getUint32(i, true)));
}}
return result;
}}
Expand Down Expand Up @@ -1768,47 +1766,51 @@ impl<'a> Context<'a> {
}

fn expose_int8_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("Int8", memory)
self.memview("Int8Array", memory)
}

fn expose_uint8_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("Uint8", memory)
self.memview("Uint8Array", memory)
}

fn expose_clamped_uint8_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("Uint8Clamped", memory)
self.memview("Uint8ClampedArray", memory)
}

fn expose_int16_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("Int16", memory)
self.memview("Int16Array", memory)
}

fn expose_uint16_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("Uint16", memory)
self.memview("Uint16Array", memory)
}

fn expose_int32_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("Int32", memory)
self.memview("Int32Array", memory)
}

fn expose_uint32_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("Uint32", memory)
self.memview("Uint32Array", memory)
}

fn expose_int64_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("BigInt64", memory)
self.memview("BigInt64Array", memory)
}

fn expose_uint64_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("BigUint64", memory)
self.memview("BigUint64Array", memory)
}

fn expose_f32_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("Float32", memory)
self.memview("Float32Array", memory)
}

fn expose_f64_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("Float64", memory)
self.memview("Float64Array", memory)
}

fn expose_dataview_memory(&mut self, memory: MemoryId) -> MemView {
self.memview("DataView", memory)
}

fn memview(&mut self, kind: &'static str, memory: walrus::MemoryId) -> MemView {
Expand All @@ -1829,6 +1831,10 @@ impl<'a> Context<'a> {
cache = cache,
mem = mem
)
} else if kind == "DataView" {
// `DataView`s throw when accessing detached memory, including `byteLength`.
// However this requires JS engine support, so we fallback to comparing the buffer.
format!("{cache}.buffer.detached === true || ({cache}.buffer.detached === undefined && {cache}.buffer !== wasm.{mem}.buffer)", cache = cache)
} else {
// Otherwise, we can do a quicker check of whether the buffer's been detached,
// which is indicated by a length of 0.
Expand All @@ -1841,7 +1847,7 @@ impl<'a> Context<'a> {
"
function {name}() {{
if ({cache} === null || {resized_check}) {{
{cache} = new {kind}Array(wasm.{mem}.buffer);
{cache} = new {kind}(wasm.{mem}.buffer);
}}
return {cache};
}}
Expand Down
26 changes: 13 additions & 13 deletions crates/cli/tests/reference/anyref-import-catch.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ let cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true

cachedTextDecoder.decode();

let cachedUint8Memory0 = null;
let cachedUint8ArrayMemory0 = null;

function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
function getUint8ArrayMemory0() {
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
return cachedUint8ArrayMemory0;
}

function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
}

function addToExternrefTable0(obj) {
Expand All @@ -39,13 +39,13 @@ function handleError(f, args) {
}
}

let cachedInt32Memory0 = null;
let cachedDataViewMemory0 = null;

function getInt32Memory0() {
if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
function getDataViewMemory0() {
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
}
return cachedInt32Memory0;
return cachedDataViewMemory0;
}

function takeFromExternrefTable0(idx) {
Expand All @@ -59,8 +59,8 @@ export function exported() {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
wasm.exported(retptr);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
if (r1) {
throw takeFromExternrefTable0(r0);
}
Expand Down
12 changes: 6 additions & 6 deletions crates/cli/tests/reference/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ let cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true

cachedTextDecoder.decode();

let cachedUint8Memory0 = null;
let cachedUint8ArrayMemory0 = null;

function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
function getUint8ArrayMemory0() {
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
return cachedUint8ArrayMemory0;
}

function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
}

const ClassBuilderFinalization = (typeof FinalizationRegistry === 'undefined')
Expand Down
12 changes: 6 additions & 6 deletions crates/cli/tests/reference/constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ let cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true

cachedTextDecoder.decode();

let cachedUint8Memory0 = null;
let cachedUint8ArrayMemory0 = null;

function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
function getUint8ArrayMemory0() {
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
return cachedUint8ArrayMemory0;
}

function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
}

const ClassConstructorFinalization = (typeof FinalizationRegistry === 'undefined')
Expand Down
12 changes: 6 additions & 6 deletions crates/cli/tests/reference/enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ let cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true

cachedTextDecoder.decode();

let cachedUint8Memory0 = null;
let cachedUint8ArrayMemory0 = null;

function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
function getUint8ArrayMemory0() {
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
return cachedUint8ArrayMemory0;
}

function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
}
/**
* @param {Color} color
Expand Down
14 changes: 7 additions & 7 deletions crates/cli/tests/reference/import-catch.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ function handleError(f, args) {
}
}

let cachedInt32Memory0 = null;
let cachedDataViewMemory0 = null;

function getInt32Memory0() {
if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
function getDataViewMemory0() {
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
}
return cachedInt32Memory0;
return cachedDataViewMemory0;
}

function getObject(idx) { return heap[idx]; }
Expand All @@ -55,8 +55,8 @@ export function exported() {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
wasm.exported(retptr);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
if (r1) {
throw takeObject(r0);
}
Expand Down
Loading

0 comments on commit a2761f6

Please sign in to comment.