mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-04-02 10:21:07 +00:00
commit
6d167116a0
@ -8,7 +8,7 @@ environment:
|
|||||||
DEPLOY: 1
|
DEPLOY: 1
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- ps: Install-Product node 9
|
- ps: Install-Product node 10
|
||||||
- appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
- appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||||
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly
|
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly
|
||||||
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
||||||
|
@ -61,7 +61,7 @@ matrix:
|
|||||||
install:
|
install:
|
||||||
- curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash
|
- curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash
|
||||||
- source ~/.nvm/nvm.sh
|
- source ~/.nvm/nvm.sh
|
||||||
- nvm install 9
|
- nvm install 10
|
||||||
- yarn
|
- yarn
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
|
@ -492,7 +492,7 @@ All structs referenced through arguments to functions should be defined in the
|
|||||||
macro itself. Arguments allowed implement the `WasmBoundary` trait, and examples
|
macro itself. Arguments allowed implement the `WasmBoundary` trait, and examples
|
||||||
are:
|
are:
|
||||||
|
|
||||||
* Integers (not u64/i64)
|
* Integers (u64/i64 require `BigInt` support)
|
||||||
* Floats
|
* Floats
|
||||||
* Borrowed strings (`&str`)
|
* Borrowed strings (`&str`)
|
||||||
* Owned strings (`String`)
|
* Owned strings (`String`)
|
||||||
|
@ -79,6 +79,8 @@ pub enum VectorKind {
|
|||||||
U16,
|
U16,
|
||||||
I32,
|
I32,
|
||||||
U32,
|
U32,
|
||||||
|
I64,
|
||||||
|
U64,
|
||||||
F32,
|
F32,
|
||||||
F64,
|
F64,
|
||||||
String,
|
String,
|
||||||
@ -139,8 +141,6 @@ impl Descriptor {
|
|||||||
Descriptor::U16 |
|
Descriptor::U16 |
|
||||||
Descriptor::I32 |
|
Descriptor::I32 |
|
||||||
Descriptor::U32 |
|
Descriptor::U32 |
|
||||||
Descriptor::I64 |
|
|
||||||
Descriptor::U64 |
|
|
||||||
Descriptor::F32 |
|
Descriptor::F32 |
|
||||||
Descriptor::F64 |
|
Descriptor::F64 |
|
||||||
Descriptor::Enum => true,
|
Descriptor::Enum => true,
|
||||||
@ -148,6 +148,14 @@ impl Descriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_64bit(&self) -> Option<bool> {
|
||||||
|
match *self {
|
||||||
|
Descriptor::I64 => Some(true),
|
||||||
|
Descriptor::U64 => Some(false),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_ref_anyref(&self) -> bool {
|
pub fn is_ref_anyref(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Descriptor::Ref(ref s) => s.is_anyref(),
|
Descriptor::Ref(ref s) => s.is_anyref(),
|
||||||
@ -199,9 +207,11 @@ impl Descriptor {
|
|||||||
Descriptor::I8 => Some(VectorKind::I8),
|
Descriptor::I8 => Some(VectorKind::I8),
|
||||||
Descriptor::I16 => Some(VectorKind::I16),
|
Descriptor::I16 => Some(VectorKind::I16),
|
||||||
Descriptor::I32 => Some(VectorKind::I32),
|
Descriptor::I32 => Some(VectorKind::I32),
|
||||||
|
Descriptor::I64 => Some(VectorKind::I64),
|
||||||
Descriptor::U8 => Some(VectorKind::U8),
|
Descriptor::U8 => Some(VectorKind::U8),
|
||||||
Descriptor::U16 => Some(VectorKind::U16),
|
Descriptor::U16 => Some(VectorKind::U16),
|
||||||
Descriptor::U32 => Some(VectorKind::U32),
|
Descriptor::U32 => Some(VectorKind::U32),
|
||||||
|
Descriptor::U64 => Some(VectorKind::U64),
|
||||||
Descriptor::F32 => Some(VectorKind::F32),
|
Descriptor::F32 => Some(VectorKind::F32),
|
||||||
Descriptor::F64 => Some(VectorKind::F64),
|
Descriptor::F64 => Some(VectorKind::F64),
|
||||||
Descriptor::Anyref => Some(VectorKind::Anyref),
|
Descriptor::Anyref => Some(VectorKind::Anyref),
|
||||||
@ -290,6 +300,8 @@ impl VectorKind {
|
|||||||
VectorKind::U16 => "Uint16Array",
|
VectorKind::U16 => "Uint16Array",
|
||||||
VectorKind::I32 => "Int32Array",
|
VectorKind::I32 => "Int32Array",
|
||||||
VectorKind::U32 => "Uint32Array",
|
VectorKind::U32 => "Uint32Array",
|
||||||
|
VectorKind::I64 => "BigInt64Array",
|
||||||
|
VectorKind::U64 => "BigUint64Array",
|
||||||
VectorKind::F32 => "Float32Array",
|
VectorKind::F32 => "Float32Array",
|
||||||
VectorKind::F64 => "Float64Array",
|
VectorKind::F64 => "Float64Array",
|
||||||
VectorKind::Anyref => "any[]",
|
VectorKind::Anyref => "any[]",
|
||||||
@ -305,6 +317,8 @@ impl VectorKind {
|
|||||||
VectorKind::U16 => 2,
|
VectorKind::U16 => 2,
|
||||||
VectorKind::I32 => 4,
|
VectorKind::I32 => 4,
|
||||||
VectorKind::U32 => 4,
|
VectorKind::U32 => 4,
|
||||||
|
VectorKind::I64 => 8,
|
||||||
|
VectorKind::U64 => 8,
|
||||||
VectorKind::F32 => 4,
|
VectorKind::F32 => 4,
|
||||||
VectorKind::F64 => 8,
|
VectorKind::F64 => 8,
|
||||||
VectorKind::Anyref => 4,
|
VectorKind::Anyref => 4,
|
||||||
|
@ -168,6 +168,29 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
return Ok(self)
|
return Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(signed) = arg.get_64bit() {
|
||||||
|
let f = if signed {
|
||||||
|
self.cx.expose_int64_cvt_shim()
|
||||||
|
} else {
|
||||||
|
self.cx.expose_uint64_cvt_shim()
|
||||||
|
};
|
||||||
|
self.cx.expose_uint32_memory();
|
||||||
|
self.cx.expose_global_argument_ptr()?;
|
||||||
|
self.js_arguments.push((name.clone(), "BigInt".to_string()));
|
||||||
|
self.prelude(&format!("\
|
||||||
|
{f}[0] = {name};\n\
|
||||||
|
const lo{i} = u32CvtShim[0];\n\
|
||||||
|
const hi{i} = u32CvtShim[1];\n\
|
||||||
|
",
|
||||||
|
i = i,
|
||||||
|
f = f,
|
||||||
|
name = name,
|
||||||
|
));
|
||||||
|
self.rust_arguments.push(format!("lo{}", i));
|
||||||
|
self.rust_arguments.push(format!("hi{}", i));
|
||||||
|
return Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
if arg.is_ref_anyref() {
|
if arg.is_ref_anyref() {
|
||||||
self.js_arguments.push((name.clone(), "any".to_string()));
|
self.js_arguments.push((name.clone(), "any".to_string()));
|
||||||
self.cx.expose_borrowed_objects();
|
self.cx.expose_borrowed_objects();
|
||||||
@ -252,6 +275,25 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
return Ok(self)
|
return Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(signed) = ty.get_64bit() {
|
||||||
|
self.ret_ty = "BigInt".to_string();
|
||||||
|
self.cx.expose_global_argument_ptr()?;
|
||||||
|
let f = if signed {
|
||||||
|
self.cx.expose_int64_memory();
|
||||||
|
"getInt64Memory"
|
||||||
|
} else {
|
||||||
|
self.cx.expose_uint64_memory();
|
||||||
|
"getUint64Memory"
|
||||||
|
};
|
||||||
|
self.prelude("const retptr = globalArgumentPtr();");
|
||||||
|
self.rust_arguments.insert(0, "retptr".to_string());
|
||||||
|
self.ret_expr = format!("\
|
||||||
|
RET;\n\
|
||||||
|
return {}()[retptr / 8];\n\
|
||||||
|
", f);
|
||||||
|
return Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
match *ty {
|
match *ty {
|
||||||
Descriptor::Boolean => {
|
Descriptor::Boolean => {
|
||||||
self.ret_ty = "boolean".to_string();
|
self.ret_ty = "boolean".to_string();
|
||||||
|
@ -787,80 +787,52 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn expose_pass_array8_to_wasm(&mut self) -> Result<(), Error> {
|
fn expose_pass_array8_to_wasm(&mut self) -> Result<(), Error> {
|
||||||
if !self.exposed_globals.insert("pass_array8_to_wasm") {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
self.require_internal_export("__wbindgen_malloc")?;
|
|
||||||
self.expose_uint8_memory();
|
self.expose_uint8_memory();
|
||||||
self.global(&format!("
|
self.pass_array_to_wasm("passArray8ToWasm", "getUint8Memory", 1)
|
||||||
function passArray8ToWasm(arg) {{
|
|
||||||
const ptr = wasm.__wbindgen_malloc(arg.length);
|
|
||||||
getUint8Memory().set(arg, ptr);
|
|
||||||
return [ptr, arg.length];
|
|
||||||
}}
|
|
||||||
"));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_pass_array16_to_wasm(&mut self) -> Result<(), Error> {
|
fn expose_pass_array16_to_wasm(&mut self) -> Result<(), Error> {
|
||||||
if !self.exposed_globals.insert("pass_array16_to_wasm") {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
self.require_internal_export("__wbindgen_malloc")?;
|
|
||||||
self.expose_uint16_memory();
|
self.expose_uint16_memory();
|
||||||
self.global(&format!("
|
self.pass_array_to_wasm("passArray16ToWasm", "getUint16Memory", 2)
|
||||||
function passArray16ToWasm(arg) {{
|
|
||||||
const ptr = wasm.__wbindgen_malloc(arg.length * 2);
|
|
||||||
getUint16Memory().set(arg, ptr / 2);
|
|
||||||
return [ptr, arg.length];
|
|
||||||
}}
|
|
||||||
"));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_pass_array32_to_wasm(&mut self) -> Result<(), Error> {
|
fn expose_pass_array32_to_wasm(&mut self) -> Result<(), Error> {
|
||||||
if !self.exposed_globals.insert("pass_array32_to_wasm") {
|
|
||||||
return Ok(())
|
|
||||||
}
|
|
||||||
self.require_internal_export("__wbindgen_malloc")?;
|
|
||||||
self.expose_uint32_memory();
|
self.expose_uint32_memory();
|
||||||
self.global(&format!("
|
self.pass_array_to_wasm("passArray32ToWasm", "getUint32Memory", 4)
|
||||||
function passArray32ToWasm(arg) {{
|
}
|
||||||
const ptr = wasm.__wbindgen_malloc(arg.length * 4);
|
|
||||||
getUint32Memory().set(arg, ptr / 4);
|
fn expose_pass_array64_to_wasm(&mut self) -> Result<(), Error> {
|
||||||
return [ptr, arg.length];
|
self.expose_uint64_memory();
|
||||||
}}
|
self.pass_array_to_wasm("passArray64ToWasm", "getUint64Memory", 8)
|
||||||
"));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_pass_array_f32_to_wasm(&mut self) -> Result<(), Error> {
|
fn expose_pass_array_f32_to_wasm(&mut self) -> Result<(), Error> {
|
||||||
if !self.exposed_globals.insert("pass_array_f32_to_wasm") {
|
self.expose_f32_memory();
|
||||||
return Ok(())
|
self.pass_array_to_wasm("passArrayF32ToWasm", "getFloat32Memory", 4)
|
||||||
}
|
|
||||||
self.require_internal_export("__wbindgen_malloc")?;
|
|
||||||
self.global(&format!("
|
|
||||||
function passArrayF32ToWasm(arg) {{
|
|
||||||
const ptr = wasm.__wbindgen_malloc(arg.length * 4);
|
|
||||||
new Float32Array(wasm.memory.buffer).set(arg, ptr / 4);
|
|
||||||
return [ptr, arg.length];
|
|
||||||
}}
|
|
||||||
"));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_pass_array_f64_to_wasm(&mut self) -> Result<(), Error> {
|
fn expose_pass_array_f64_to_wasm(&mut self) -> Result<(), Error> {
|
||||||
if !self.exposed_globals.insert("pass_array_f64_to_wasm") {
|
self.expose_f64_memory();
|
||||||
|
self.pass_array_to_wasm("passArrayF64ToWasm", "getFloat64Memory", 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pass_array_to_wasm(&mut self,
|
||||||
|
name: &'static str,
|
||||||
|
delegate: &str,
|
||||||
|
size: usize) -> Result<(), Error>
|
||||||
|
{
|
||||||
|
if !self.exposed_globals.insert(name) {
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
self.require_internal_export("__wbindgen_malloc")?;
|
self.require_internal_export("__wbindgen_malloc")?;
|
||||||
|
self.expose_uint64_memory();
|
||||||
self.global(&format!("
|
self.global(&format!("
|
||||||
function passArrayF64ToWasm(arg) {{
|
function {}(arg) {{
|
||||||
const ptr = wasm.__wbindgen_malloc(arg.length * 8);
|
const ptr = wasm.__wbindgen_malloc(arg.length * {size});
|
||||||
new Float64Array(wasm.memory.buffer).set(arg, ptr / 8);
|
{}().set(arg, ptr / {size});
|
||||||
return [ptr, arg.length];
|
return [ptr, arg.length];
|
||||||
}}
|
}}
|
||||||
"));
|
", name, delegate, size = size));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -980,6 +952,16 @@ impl<'a> Context<'a> {
|
|||||||
self.arrayget("getArrayU32FromWasm", "getUint32Memory", 4);
|
self.arrayget("getArrayU32FromWasm", "getUint32Memory", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expose_get_array_i64_from_wasm(&mut self) {
|
||||||
|
self.expose_int64_memory();
|
||||||
|
self.arrayget("getArrayI64FromWasm", "getInt64Memory", 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expose_get_array_u64_from_wasm(&mut self) {
|
||||||
|
self.expose_uint64_memory();
|
||||||
|
self.arrayget("getArrayU64FromWasm", "getUint64Memory", 8);
|
||||||
|
}
|
||||||
|
|
||||||
fn expose_get_array_f32_from_wasm(&mut self) {
|
fn expose_get_array_f32_from_wasm(&mut self) {
|
||||||
self.expose_f32_memory();
|
self.expose_f32_memory();
|
||||||
self.arrayget("getArrayF32FromWasm", "getFloat32Memory", 4);
|
self.arrayget("getArrayF32FromWasm", "getFloat32Memory", 4);
|
||||||
@ -1029,6 +1011,14 @@ impl<'a> Context<'a> {
|
|||||||
self.memview("getUint32Memory", "Uint32Array");
|
self.memview("getUint32Memory", "Uint32Array");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expose_int64_memory(&mut self) {
|
||||||
|
self.memview("getInt64Memory", "BigInt64Array");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expose_uint64_memory(&mut self) {
|
||||||
|
self.memview("getUint64Memory", "BigUint64Array");
|
||||||
|
}
|
||||||
|
|
||||||
fn expose_f32_memory(&mut self) {
|
fn expose_f32_memory(&mut self) {
|
||||||
self.memview("getFloat32Memory", "Float32Array");
|
self.memview("getFloat32Memory", "Float32Array");
|
||||||
}
|
}
|
||||||
@ -1067,6 +1057,14 @@ impl<'a> Context<'a> {
|
|||||||
self.expose_uint32_memory();
|
self.expose_uint32_memory();
|
||||||
"getUint32Memory"
|
"getUint32Memory"
|
||||||
}
|
}
|
||||||
|
VectorKind::I64 => {
|
||||||
|
self.expose_int64_memory();
|
||||||
|
"getInt64Memory"
|
||||||
|
}
|
||||||
|
VectorKind::U64 => {
|
||||||
|
self.expose_uint64_memory();
|
||||||
|
"getUint64Memory"
|
||||||
|
}
|
||||||
VectorKind::F32 => {
|
VectorKind::F32 => {
|
||||||
self.expose_f32_memory();
|
self.expose_f32_memory();
|
||||||
"getFloat32Memory"
|
"getFloat32Memory"
|
||||||
@ -1204,6 +1202,11 @@ impl<'a> Context<'a> {
|
|||||||
self.expose_pass_array32_to_wasm()?;
|
self.expose_pass_array32_to_wasm()?;
|
||||||
"passArray32ToWasm"
|
"passArray32ToWasm"
|
||||||
}
|
}
|
||||||
|
VectorKind::I64 |
|
||||||
|
VectorKind::U64 => {
|
||||||
|
self.expose_pass_array64_to_wasm()?;
|
||||||
|
"passArray64ToWasm"
|
||||||
|
}
|
||||||
VectorKind::F32 => {
|
VectorKind::F32 => {
|
||||||
self.expose_pass_array_f32_to_wasm()?;
|
self.expose_pass_array_f32_to_wasm()?;
|
||||||
"passArrayF32ToWasm"
|
"passArrayF32ToWasm"
|
||||||
@ -1249,6 +1252,14 @@ impl<'a> Context<'a> {
|
|||||||
self.expose_get_array_u32_from_wasm();
|
self.expose_get_array_u32_from_wasm();
|
||||||
"getArrayU32FromWasm"
|
"getArrayU32FromWasm"
|
||||||
}
|
}
|
||||||
|
VectorKind::I64 => {
|
||||||
|
self.expose_get_array_i64_from_wasm();
|
||||||
|
"getArrayI64FromWasm"
|
||||||
|
}
|
||||||
|
VectorKind::U64 => {
|
||||||
|
self.expose_get_array_u64_from_wasm();
|
||||||
|
"getArrayU64FromWasm"
|
||||||
|
}
|
||||||
VectorKind::F32 => {
|
VectorKind::F32 => {
|
||||||
self.expose_get_array_f32_from_wasm();
|
self.expose_get_array_f32_from_wasm();
|
||||||
"getArrayF32FromWasm"
|
"getArrayF32FromWasm"
|
||||||
@ -1320,6 +1331,35 @@ impl<'a> Context<'a> {
|
|||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expose_u32_cvt_shim(&mut self) -> &'static str {
|
||||||
|
let name = "u32CvtShim";
|
||||||
|
if !self.exposed_globals.insert(name) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
self.global(&format!("const {} = new Uint32Array(2);", name));
|
||||||
|
name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expose_int64_cvt_shim(&mut self) -> &'static str {
|
||||||
|
let name = "int64CvtShim";
|
||||||
|
if !self.exposed_globals.insert(name) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
let n = self.expose_u32_cvt_shim();
|
||||||
|
self.global(&format!("const {} = new BigInt64Array({}.buffer);", name, n));
|
||||||
|
name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expose_uint64_cvt_shim(&mut self) -> &'static str {
|
||||||
|
let name = "uint64CvtShim";
|
||||||
|
if !self.exposed_globals.insert(name) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
let n = self.expose_u32_cvt_shim();
|
||||||
|
self.global(&format!("const {} = new BigUint64Array({}.buffer);", name, n));
|
||||||
|
name
|
||||||
|
}
|
||||||
|
|
||||||
fn gc(&mut self) -> Result<(), Error> {
|
fn gc(&mut self) -> Result<(), Error> {
|
||||||
let module = mem::replace(self.module, Module::default());
|
let module = mem::replace(self.module, Module::default());
|
||||||
let wasm_bytes = parity_wasm::serialize(module)?;
|
let wasm_bytes = parity_wasm::serialize(module)?;
|
||||||
|
@ -98,6 +98,28 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(signed) = arg.get_64bit() {
|
||||||
|
let f = if signed {
|
||||||
|
self.cx.expose_int64_cvt_shim()
|
||||||
|
} else {
|
||||||
|
self.cx.expose_uint64_cvt_shim()
|
||||||
|
};
|
||||||
|
let hi = self.shim_argument();
|
||||||
|
let name = format!("n{}", abi);
|
||||||
|
self.prelude(&format!("\
|
||||||
|
u32CvtShim[0] = {lo};\n\
|
||||||
|
u32CvtShim[1] = {hi};\n\
|
||||||
|
const {name} = {f}[0];\n\
|
||||||
|
",
|
||||||
|
lo = abi,
|
||||||
|
hi = hi,
|
||||||
|
f = f,
|
||||||
|
name = name,
|
||||||
|
));
|
||||||
|
self.js_arguments.push(name);
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(class) = arg.rust_struct() {
|
if let Some(class) = arg.rust_struct() {
|
||||||
if arg.is_by_ref() {
|
if arg.is_by_ref() {
|
||||||
bail!("cannot invoke JS functions with custom ref types yet")
|
bail!("cannot invoke JS functions with custom ref types yet")
|
||||||
@ -229,6 +251,21 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
self.ret_expr = "return JS;".to_string();
|
self.ret_expr = "return JS;".to_string();
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
|
if let Some(signed) = ty.get_64bit() {
|
||||||
|
let f = if signed {
|
||||||
|
self.cx.expose_int64_memory();
|
||||||
|
"getInt64Memory"
|
||||||
|
} else {
|
||||||
|
self.cx.expose_uint64_memory();
|
||||||
|
"getUint64Memory"
|
||||||
|
};
|
||||||
|
self.shim_arguments.insert(0, "ret".to_string());
|
||||||
|
self.ret_expr = format!("\
|
||||||
|
const val = JS;\n\
|
||||||
|
{}()[ret / 8] = val;\n\
|
||||||
|
", f);
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
self.ret_expr = match *ty {
|
self.ret_expr = match *ty {
|
||||||
Descriptor::Boolean => "return JS ? 1 : 0;".to_string(),
|
Descriptor::Boolean => "return JS ? 1 : 0;".to_string(),
|
||||||
Descriptor::Anyref => {
|
Descriptor::Anyref => {
|
||||||
|
@ -55,9 +55,7 @@ pub trait Stack {
|
|||||||
pub unsafe trait WasmAbi {}
|
pub unsafe trait WasmAbi {}
|
||||||
|
|
||||||
unsafe impl WasmAbi for u32 {}
|
unsafe impl WasmAbi for u32 {}
|
||||||
unsafe impl WasmAbi for u64 {}
|
|
||||||
unsafe impl WasmAbi for i32 {}
|
unsafe impl WasmAbi for i32 {}
|
||||||
unsafe impl WasmAbi for i64 {}
|
|
||||||
unsafe impl WasmAbi for f32 {}
|
unsafe impl WasmAbi for f32 {}
|
||||||
unsafe impl WasmAbi for f64 {}
|
unsafe impl WasmAbi for f64 {}
|
||||||
|
|
||||||
@ -83,7 +81,30 @@ macro_rules! simple {
|
|||||||
)*)
|
)*)
|
||||||
}
|
}
|
||||||
|
|
||||||
simple!(u32 u64 i32 i64 f32 f64);
|
simple!(u32 i32 f32 f64);
|
||||||
|
|
||||||
|
macro_rules! sixtyfour {
|
||||||
|
($($t:tt)*) => ($(
|
||||||
|
impl IntoWasmAbi for $t {
|
||||||
|
type Abi = WasmSlice;
|
||||||
|
fn into_abi(self, _extra: &mut Stack) -> WasmSlice {
|
||||||
|
WasmSlice {
|
||||||
|
ptr: self as u32,
|
||||||
|
len: (self >> 32) as u32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromWasmAbi for $t {
|
||||||
|
type Abi = WasmSlice;
|
||||||
|
unsafe fn from_abi(js: WasmSlice, _extra: &mut Stack) -> $t {
|
||||||
|
(js.ptr as $t) | ((js.len as $t) << 32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*)
|
||||||
|
}
|
||||||
|
|
||||||
|
sixtyfour!(i64 u64);
|
||||||
|
|
||||||
macro_rules! as_u32 {
|
macro_rules! as_u32 {
|
||||||
($($t:tt)*) => ($(
|
($($t:tt)*) => ($(
|
||||||
@ -217,7 +238,7 @@ macro_rules! vectors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vectors! {
|
vectors! {
|
||||||
u8 i8 u16 i16 u32 i32 f32 f64
|
u8 i8 u16 i16 u32 i32 u64 i64 f32 f64
|
||||||
}
|
}
|
||||||
|
|
||||||
if_std! {
|
if_std! {
|
||||||
|
@ -4,7 +4,8 @@ use std::env;
|
|||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::{self, Write, Read};
|
use std::io::{self, Write, Read};
|
||||||
use std::path::{PathBuf, Path};
|
use std::path::{PathBuf, Path};
|
||||||
use std::process::Command;
|
use std::process::{Command, Stdio};
|
||||||
|
use std::sync::{Once, ONCE_INIT};
|
||||||
use std::sync::atomic::*;
|
use std::sync::atomic::*;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ struct Project {
|
|||||||
no_std: bool,
|
no_std: bool,
|
||||||
serde: bool,
|
serde: bool,
|
||||||
rlib: bool,
|
rlib: bool,
|
||||||
|
node_args: Vec<String>,
|
||||||
deps: Vec<String>,
|
deps: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +35,7 @@ fn project() -> Project {
|
|||||||
serde: false,
|
serde: false,
|
||||||
rlib: false,
|
rlib: false,
|
||||||
deps: Vec::new(),
|
deps: Vec::new(),
|
||||||
|
node_args: Vec::new(),
|
||||||
files: vec![
|
files: vec![
|
||||||
("Cargo.lock".to_string(), lockfile),
|
("Cargo.lock".to_string(), lockfile),
|
||||||
|
|
||||||
@ -120,6 +123,40 @@ fn root() -> PathBuf {
|
|||||||
return me
|
return me
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assert_bigint_support() -> Option<&'static str> {
|
||||||
|
static BIGINT_SUPPORED: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||||
|
static INIT: Once = ONCE_INIT;
|
||||||
|
|
||||||
|
INIT.call_once(|| {
|
||||||
|
let mut cmd = Command::new("node");
|
||||||
|
cmd.arg("-e").arg("BigInt");
|
||||||
|
cmd.stdin(Stdio::null())
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.stderr(Stdio::piped());
|
||||||
|
if cmd.status().unwrap().success() {
|
||||||
|
BIGINT_SUPPORED.store(1, Ordering::SeqCst);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.arg("--harmony-bigint");
|
||||||
|
if cmd.status().unwrap().success() {
|
||||||
|
BIGINT_SUPPORED.store(2, Ordering::SeqCst);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
match BIGINT_SUPPORED.load(Ordering::SeqCst) {
|
||||||
|
1 => return None,
|
||||||
|
2 => return Some("--harmony-bigint"),
|
||||||
|
_ => {
|
||||||
|
panic!("the version of node.js that is installed for these tests \
|
||||||
|
does not support `BigInt`, you may wish to try installing \
|
||||||
|
node 10 to fix this")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
impl Project {
|
impl Project {
|
||||||
fn file(&mut self, name: &str, contents: &str) -> &mut Project {
|
fn file(&mut self, name: &str, contents: &str) -> &mut Project {
|
||||||
self.files.push((name.to_string(), contents.to_string()));
|
self.files.push((name.to_string(), contents.to_string()));
|
||||||
@ -165,6 +202,13 @@ impl Project {
|
|||||||
format!("test{}", IDX.with(|x| *x))
|
format!("test{}", IDX.with(|x| *x))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn requires_bigint(&mut self) -> &mut Project {
|
||||||
|
if let Some(arg) = assert_bigint_support() {
|
||||||
|
self.node_args.push(arg.to_string());
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn build(&mut self) -> (PathBuf, PathBuf) {
|
fn build(&mut self) -> (PathBuf, PathBuf) {
|
||||||
let mut manifest = format!(r#"
|
let mut manifest = format!(r#"
|
||||||
[package]
|
[package]
|
||||||
@ -265,6 +309,7 @@ impl Project {
|
|||||||
|
|
||||||
if self.node {
|
if self.node {
|
||||||
let mut cmd = Command::new("node");
|
let mut cmd = Command::new("node");
|
||||||
|
cmd.args(&self.node_args);
|
||||||
cmd.arg(root.join("run-node.js"))
|
cmd.arg(root.join("run-node.js"))
|
||||||
.current_dir(&root);
|
.current_dir(&root);
|
||||||
run(&mut cmd, "node");
|
run(&mut cmd, "node");
|
||||||
@ -281,6 +326,7 @@ impl Project {
|
|||||||
run(&mut cmd, "yarn");
|
run(&mut cmd, "yarn");
|
||||||
|
|
||||||
let mut cmd = Command::new("node");
|
let mut cmd = Command::new("node");
|
||||||
|
cmd.args(&self.node_args);
|
||||||
cmd.arg(root.join("bundle.js"))
|
cmd.arg(root.join("bundle.js"))
|
||||||
.current_dir(&root);
|
.current_dir(&root);
|
||||||
run(&mut cmd, "node");
|
run(&mut cmd, "node");
|
||||||
@ -335,3 +381,4 @@ mod simple;
|
|||||||
mod slice;
|
mod slice;
|
||||||
mod structural;
|
mod structural;
|
||||||
mod non_wasm;
|
mod non_wasm;
|
||||||
|
mod u64;
|
||||||
|
100
tests/all/u64.rs
Normal file
100
tests/all/u64.rs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
use super::project;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn works() {
|
||||||
|
project()
|
||||||
|
.requires_bigint()
|
||||||
|
.file("src/lib.rs", r#"
|
||||||
|
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
||||||
|
|
||||||
|
extern crate wasm_bindgen;
|
||||||
|
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "./test")]
|
||||||
|
extern {
|
||||||
|
fn js_i64_round(a: i64) -> i64;
|
||||||
|
fn js_u64_round(a: u64) -> u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn zero() -> u64 { 0 }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn one() -> u64 { 1 }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn neg_one() -> i64 { -1 }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u32_max() -> u64 { u32::max_value() as u64 }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i32_min() -> i64 { i32::min_value() as i64 }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u64_max() -> u64 { u64::max_value() }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i64_min() -> i64 { i64::min_value() }
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i64_round(a: i64) -> i64 { js_i64_round(a) }
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u64_round(a: u64) -> u64 { js_u64_round(a) }
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn i64_slice(a: &[i64]) -> Vec<i64> { a.to_vec() }
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn u64_slice(a: &[u64]) -> Vec<u64> { a.to_vec() }
|
||||||
|
"#)
|
||||||
|
.file("test.js", r#"
|
||||||
|
import * as wasm from './out';
|
||||||
|
|
||||||
|
function assertEq(a, b) {
|
||||||
|
console.log(a, '?=', b);
|
||||||
|
if (a === b)
|
||||||
|
return;
|
||||||
|
throw new Error('not equal');
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertArrayEq(a, b) {
|
||||||
|
console.log(a, '?=', b);
|
||||||
|
if (a.length !== b.length)
|
||||||
|
throw new Error('not equal');
|
||||||
|
for (let i = 0; i < a.length; i++)
|
||||||
|
assertEq(a[i], b[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function test() {
|
||||||
|
assertEq(wasm.zero(), BigInt(0));
|
||||||
|
assertEq(wasm.one(), BigInt(1));
|
||||||
|
assertEq(wasm.neg_one(), BigInt(-1));
|
||||||
|
assertEq(wasm.u32_max(), BigInt(4294967295));
|
||||||
|
assertEq(wasm.i32_min(), BigInt(-2147483648));
|
||||||
|
assertEq(wasm.u64_max(), BigInt('18446744073709551615'));
|
||||||
|
assertEq(wasm.i64_min(), BigInt('-9223372036854775808'));
|
||||||
|
|
||||||
|
assertEq(wasm.i64_round(BigInt(0)), BigInt(0));
|
||||||
|
assertEq(wasm.i64_round(BigInt(1)), BigInt(1));
|
||||||
|
assertEq(wasm.i64_round(BigInt(-1)), BigInt(-1));
|
||||||
|
assertEq(wasm.u64_round(BigInt(0)), BigInt(0));
|
||||||
|
assertEq(wasm.u64_round(BigInt(1)), BigInt(1));
|
||||||
|
assertEq(wasm.u64_round(BigInt(1) << BigInt(64)), BigInt(0));
|
||||||
|
|
||||||
|
const u64_max = BigInt('18446744073709551615');
|
||||||
|
const i64_min = BigInt('-9223372036854775808');
|
||||||
|
assertEq(wasm.i64_round(i64_min), i64_min);
|
||||||
|
assertEq(wasm.u64_round(u64_max), u64_max);
|
||||||
|
|
||||||
|
assertArrayEq(wasm.u64_slice([]), new BigUint64Array());
|
||||||
|
assertArrayEq(wasm.i64_slice([]), new BigInt64Array());
|
||||||
|
const arr1 = new BigUint64Array([BigInt(1), BigInt(2)]);
|
||||||
|
assertArrayEq(wasm.u64_slice([BigInt(1), BigInt(2)]), arr1);
|
||||||
|
const arr2 = new BigInt64Array([BigInt(1), BigInt(2)]);
|
||||||
|
assertArrayEq(wasm.i64_slice([BigInt(1), BigInt(2)]), arr2);
|
||||||
|
|
||||||
|
assertArrayEq(wasm.i64_slice([i64_min]), new BigInt64Array([i64_min]));
|
||||||
|
assertArrayEq(wasm.u64_slice([u64_max]), new BigUint64Array([u64_max]));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function js_i64_round(a) { return a; }
|
||||||
|
export function js_u64_round(a) { return a; }
|
||||||
|
"#)
|
||||||
|
.test();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user