diff --git a/Cargo.lock b/Cargo.lock index 18bfacb7..a9311de0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -648,7 +648,7 @@ dependencies = [ [[package]] name = "polkavm-derive-impl" -version = "0.18.0" +version = "0.18.1" dependencies = [ "polkavm-common", "proc-macro2", diff --git a/crates/polkavm-common/src/program.rs b/crates/polkavm-common/src/program.rs index 7828fa7d..5de56c65 100644 --- a/crates/polkavm-common/src/program.rs +++ b/crates/polkavm-common/src/program.rs @@ -1468,107 +1468,107 @@ define_opcodes! { // Instructions with args: reg, reg, imm [ - [I_64, I_32] store_indirect_u8 = 110, - [I_64, I_32] store_indirect_u16 = 111, - [I_64, I_32] store_indirect_u32 = 112, - [I_64] store_indirect_u64 = 113, - [I_64, I_32] load_indirect_u8 = 114, - [I_64, I_32] load_indirect_i8 = 115, - [I_64, I_32] load_indirect_u16 = 116, - [I_64, I_32] load_indirect_i16 = 117, - [I_64, I_32] load_indirect_i32 = 119, - [I_64] load_indirect_u32 = 118, - [I_64] load_indirect_u64 = 120, - [I_64, I_32] add_imm_32 = 121, - [I_64] add_imm_64 = 139, - [I_64, I_32] and_imm = 122, - [I_64, I_32] xor_imm = 123, - [I_64, I_32] or_imm = 124, - [I_64, I_32] mul_imm_32 = 125, - [I_64] mul_imm_64 = 140, - [I_64, I_32] set_less_than_unsigned_imm = 126, - [I_64, I_32] set_less_than_signed_imm = 127, - [I_64, I_32] shift_logical_left_imm_32 = 128, - [I_64] shift_logical_left_imm_64 = 141, - [I_64, I_32] shift_logical_right_imm_32 = 129, - [I_64] shift_logical_right_imm_64 = 142, - [I_64, I_32] shift_arithmetic_right_imm_32 = 130, - [I_64] shift_arithmetic_right_imm_64 = 143, - [I_64, I_32] negate_and_add_imm_32 = 131, - [I_64] negate_and_add_imm_64 = 144, - [I_64, I_32] set_greater_than_unsigned_imm = 132, - [I_64, I_32] set_greater_than_signed_imm = 133, - [I_64, I_32] shift_logical_right_imm_alt_32 = 135, - [I_64] shift_logical_right_imm_alt_64 = 146, - [I_64, I_32] shift_arithmetic_right_imm_alt_32 = 136, - [I_64] shift_arithmetic_right_imm_alt_64 = 147, - [I_64, I_32] shift_logical_left_imm_alt_32 = 134, - [I_64] shift_logical_left_imm_alt_64 = 145, - - [I_64, I_32] cmov_if_zero_imm = 137, - [I_64, I_32] cmov_if_not_zero_imm = 138, - - [I_64, I_32] rotate_right_32_imm = 41, - [I_64, I_32] rotate_right_32_imm_alt = 42, - [I_64] rotate_right_64_imm = 43, - [I_64] rotate_right_64_imm_alt = 44, + [I_64, I_32] store_indirect_u8 = 120, + [I_64, I_32] store_indirect_u16 = 121, + [I_64, I_32] store_indirect_u32 = 122, + [I_64] store_indirect_u64 = 123, + [I_64, I_32] load_indirect_u8 = 124, + [I_64, I_32] load_indirect_i8 = 125, + [I_64, I_32] load_indirect_u16 = 126, + [I_64, I_32] load_indirect_i16 = 127, + [I_64, I_32] load_indirect_i32 = 129, + [I_64] load_indirect_u32 = 128, + [I_64] load_indirect_u64 = 130, + [I_64, I_32] add_imm_32 = 131, + [I_64] add_imm_64 = 149, + [I_64, I_32] and_imm = 132, + [I_64, I_32] xor_imm = 133, + [I_64, I_32] or_imm = 134, + [I_64, I_32] mul_imm_32 = 135, + [I_64] mul_imm_64 = 150, + [I_64, I_32] set_less_than_unsigned_imm = 136, + [I_64, I_32] set_less_than_signed_imm = 137, + [I_64, I_32] shift_logical_left_imm_32 = 138, + [I_64] shift_logical_left_imm_64 = 151, + [I_64, I_32] shift_logical_right_imm_32 = 139, + [I_64] shift_logical_right_imm_64 = 152, + [I_64, I_32] shift_arithmetic_right_imm_32 = 140, + [I_64] shift_arithmetic_right_imm_64 = 153, + [I_64, I_32] negate_and_add_imm_32 = 141, + [I_64] negate_and_add_imm_64 = 154, + [I_64, I_32] set_greater_than_unsigned_imm = 142, + [I_64, I_32] set_greater_than_signed_imm = 143, + [I_64, I_32] shift_logical_right_imm_alt_32 = 145, + [I_64] shift_logical_right_imm_alt_64 = 156, + [I_64, I_32] shift_arithmetic_right_imm_alt_32 = 146, + [I_64] shift_arithmetic_right_imm_alt_64 = 157, + [I_64, I_32] shift_logical_left_imm_alt_32 = 144, + [I_64] shift_logical_left_imm_alt_64 = 155, + + [I_64, I_32] cmov_if_zero_imm = 147, + [I_64, I_32] cmov_if_not_zero_imm = 148, + + [I_64, I_32] rotate_right_32_imm = 160, + [I_64, I_32] rotate_right_32_imm_alt = 161, + [I_64] rotate_right_64_imm = 158, + [I_64] rotate_right_64_imm_alt = 159, ] // Instructions with args: reg, reg, offset [ - [I_64, I_32] branch_eq = 150, - [I_64, I_32] branch_not_eq = 151, - [I_64, I_32] branch_less_unsigned = 152, - [I_64, I_32] branch_less_signed = 153, - [I_64, I_32] branch_greater_or_equal_unsigned = 154, - [I_64, I_32] branch_greater_or_equal_signed = 155, + [I_64, I_32] branch_eq = 170, + [I_64, I_32] branch_not_eq = 171, + [I_64, I_32] branch_less_unsigned = 172, + [I_64, I_32] branch_less_signed = 173, + [I_64, I_32] branch_greater_or_equal_unsigned = 174, + [I_64, I_32] branch_greater_or_equal_signed = 175, ] // Instructions with args: reg, reg, reg [ - [I_64, I_32] add_32 = 170, - [I_64] add_64 = 180, - [I_64, I_32] sub_32 = 171, - [I_64] sub_64 = 181, - [I_64, I_32] and = 190, - [I_64, I_32] xor = 191, - [I_64, I_32] or = 192, - [I_64, I_32] mul_32 = 172, - [I_64] mul_64 = 182, - [I_32, I_64] mul_upper_signed_signed = 193, - [I_32, I_64] mul_upper_unsigned_unsigned = 194, - [I_32, I_64] mul_upper_signed_unsigned = 195, - [I_64, I_32] set_less_than_unsigned = 196, - [I_64, I_32] set_less_than_signed = 197, - [I_64, I_32] shift_logical_left_32 = 177, - [I_64] shift_logical_left_64 = 187, - [I_64, I_32] shift_logical_right_32 = 178, - [I_64] shift_logical_right_64 = 188, - [I_64, I_32] shift_arithmetic_right_32 = 179, - [I_64] shift_arithmetic_right_64 = 189, - [I_64, I_32] div_unsigned_32 = 173, - [I_64] div_unsigned_64 = 183, - [I_64, I_32] div_signed_32 = 174, - [I_64] div_signed_64 = 184, - [I_64, I_32] rem_unsigned_32 = 175, - [I_64] rem_unsigned_64 = 185, - [I_64, I_32] rem_signed_32 = 176, - [I_64] rem_signed_64 = 186, - - [I_64, I_32] cmov_if_zero = 198, - [I_64, I_32] cmov_if_not_zero = 199, - - [I_64, I_32] and_inverted = 162, - [I_64, I_32] or_inverted = 237, - [I_64, I_32] xnor = 238, - [I_64, I_32] maximum = 245, - [I_64, I_32] maximum_unsigned = 246, - [I_64, I_32] minimum = 247, - [I_64, I_32] minimum_unsigned = 148, - [I_64, I_32] rotate_left_32 = 252, - [I_64] rotate_left_64 = 253, - [I_64, I_32] rotate_right_32 = 254, - [I_64] rotate_right_64 = 255, + [I_64, I_32] add_32 = 190, + [I_64] add_64 = 200, + [I_64, I_32] sub_32 = 191, + [I_64] sub_64 = 201, + [I_64, I_32] and = 210, + [I_64, I_32] xor = 211, + [I_64, I_32] or = 212, + [I_64, I_32] mul_32 = 192, + [I_64] mul_64 = 202, + [I_32, I_64] mul_upper_signed_signed = 213, + [I_32, I_64] mul_upper_unsigned_unsigned = 214, + [I_32, I_64] mul_upper_signed_unsigned = 215, + [I_64, I_32] set_less_than_unsigned = 216, + [I_64, I_32] set_less_than_signed = 217, + [I_64, I_32] shift_logical_left_32 = 197, + [I_64] shift_logical_left_64 = 207, + [I_64, I_32] shift_logical_right_32 = 198, + [I_64] shift_logical_right_64 = 208, + [I_64, I_32] shift_arithmetic_right_32 = 199, + [I_64] shift_arithmetic_right_64 = 209, + [I_64, I_32] div_unsigned_32 = 193, + [I_64] div_unsigned_64 = 203, + [I_64, I_32] div_signed_32 = 194, + [I_64] div_signed_64 = 204, + [I_64, I_32] rem_unsigned_32 = 195, + [I_64] rem_unsigned_64 = 205, + [I_64, I_32] rem_signed_32 = 196, + [I_64] rem_signed_64 = 206, + + [I_64, I_32] cmov_if_zero = 218, + [I_64, I_32] cmov_if_not_zero = 219, + + [I_64, I_32] and_inverted = 224, + [I_64, I_32] or_inverted = 225, + [I_64, I_32] xnor = 226, + [I_64, I_32] maximum = 227, + [I_64, I_32] maximum_unsigned = 228, + [I_64, I_32] minimum = 229, + [I_64, I_32] minimum_unsigned = 230, + [I_64, I_32] rotate_left_32 = 221, + [I_64] rotate_left_64 = 220, + [I_64, I_32] rotate_right_32 = 223, + [I_64] rotate_right_64 = 222, ] // Instructions with args: offset @@ -1593,22 +1593,22 @@ define_opcodes! { [ [I_64, I_32] move_reg = 100, [I_SBRK] sbrk = 101, - [I_64, I_32] count_leading_zero_bits_32 = 239, - [I_64] count_leading_zero_bits_64 = 240, - [I_64, I_32] count_trailing_zero_bits_32 = 241, - [I_64] count_trailing_zero_bits_64 = 242, - [I_64, I_32] count_set_bits_32 = 243, - [I_64] count_set_bits_64 = 244, - [I_64, I_32] sign_extend_8 = 45, - [I_64, I_32] sign_extend_16 = 46, - [I_64, I_32] zero_extend_16 = 47, + [I_64, I_32] count_leading_zero_bits_32 = 105, + [I_64] count_leading_zero_bits_64 = 104, + [I_64, I_32] count_trailing_zero_bits_32 = 107, + [I_64] count_trailing_zero_bits_64 = 106, + [I_64, I_32] count_set_bits_32 = 103, + [I_64] count_set_bits_64 = 102, + [I_64, I_32] sign_extend_8 = 108, + [I_64, I_32] sign_extend_16 = 109, + [I_64, I_32] zero_extend_16 = 110, [I_64, I_32] or_combine_byte = 48, - [I_64, I_32] reverse_byte = 49, + [I_64, I_32] reverse_byte = 111, ] // Instructions with args: reg, reg, imm, imm [ - [I_64, I_32] load_imm_and_jump_indirect = 160, + [I_64, I_32] load_imm_and_jump_indirect = 180, ] // Instruction with args: reg, imm64 diff --git a/crates/polkavm-derive-impl/Cargo.toml b/crates/polkavm-derive-impl/Cargo.toml index 64484d35..ef49677e 100644 --- a/crates/polkavm-derive-impl/Cargo.toml +++ b/crates/polkavm-derive-impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "polkavm-derive-impl" -version.workspace = true +version = "0.18.1" authors.workspace = true license.workspace = true edition.workspace = true diff --git a/crates/polkavm-derive-impl/src/abi_support_impl/riscv32.rs b/crates/polkavm-derive-impl/src/abi_support_impl/riscv32.rs index 55d73262..6fa35e4e 100644 --- a/crates/polkavm-derive-impl/src/abi_support_impl/riscv32.rs +++ b/crates/polkavm-derive-impl/src/abi_support_impl/riscv32.rs @@ -64,6 +64,28 @@ impl IntoHost for i64 { } } +#[cfg(target_pointer_width = "32")] +impl IntoHost for (usize, usize) { + type Regs = (u32, u32); + type Destructor = (); + + #[inline(always)] + fn into_host((a, b): Self) -> (Self::Regs, ()) { + ((a as u32, b as u32), ()) + } +} + +#[cfg(target_pointer_width = "32")] +impl IntoHost for (u32, u32) { + type Regs = (u32, u32); + type Destructor = (); + + #[inline(always)] + fn into_host(value: Self) -> (Self::Regs, ()) { + (value, ()) + } +} + #[cfg(target_pointer_width = "32")] impl FromHost for u32 { type Regs = (u32,); diff --git a/crates/polkavm-derive-impl/src/abi_support_impl/riscv64.rs b/crates/polkavm-derive-impl/src/abi_support_impl/riscv64.rs index cb06c705..b38633da 100644 --- a/crates/polkavm-derive-impl/src/abi_support_impl/riscv64.rs +++ b/crates/polkavm-derive-impl/src/abi_support_impl/riscv64.rs @@ -64,6 +64,28 @@ impl IntoHost for isize { } } +#[cfg(target_pointer_width = "64")] +impl IntoHost for (usize, usize) { + type Regs = (u64, u64); + type Destructor = (); + + #[inline(always)] + fn into_host((a, b): Self) -> (Self::Regs, ()) { + ((a as u64, b as u64), ()) + } +} + +#[cfg(target_pointer_width = "64")] +impl IntoHost for (u64, u64) { + type Regs = (u64, u64); + type Destructor = (); + + #[inline(always)] + fn into_host(value: Self) -> (Self::Regs, ()) { + (value, ()) + } +} + #[cfg(target_pointer_width = "64")] impl FromHost for u32 { type Regs = (u64,); diff --git a/crates/polkavm/src/tests.rs b/crates/polkavm/src/tests.rs index 1b824417..e085cf3c 100644 --- a/crates/polkavm/src/tests.rs +++ b/crates/polkavm/src/tests.rs @@ -2330,11 +2330,40 @@ fn test_blob_negate_and_add(config: Config, optimize: bool, is_64_bit: bool) { } } -fn test_blob_return_tuple(config: Config, optimize: bool, is_64_bit: bool) { +fn test_blob_return_tuple_from_import(config: Config, optimize: bool, is_64_bit: bool) { let mut i = TestInstance::new(&config, optimize, is_64_bit); i.call::<(), ()>("test_return_tuple", ()).unwrap(); } +fn test_blob_return_tuple_from_export(config: Config, optimize: bool, is_64_bit: bool) { + let mut i = TestInstance::new(&config, optimize, is_64_bit); + if is_64_bit { + let a0 = 0x123456789abcdefe_u64; + let a1 = 0x1122334455667788_u64; + i.call::<(), ()>("export_return_tuple_u64", ()).unwrap(); + assert_eq!(i.instance.reg(Reg::A0), a0); + assert_eq!(i.instance.reg(Reg::A1), a1); + + i.instance.set_reg(Reg::A0, 0); + i.instance.set_reg(Reg::A1, 0); + i.call::<(), ()>("export_return_tuple_usize", ()).unwrap(); + assert_eq!(i.instance.reg(Reg::A0), a0); + assert_eq!(i.instance.reg(Reg::A1), a1); + } else { + let a0 = 0x12345678_u64; + let a1 = 0x9abcdefe_u64; + i.call::<(), ()>("export_return_tuple_u32", ()).unwrap(); + assert_eq!(i.instance.reg(Reg::A0), a0); + assert_eq!(i.instance.reg(Reg::A1), a1); + + i.instance.set_reg(Reg::A0, 0); + i.instance.set_reg(Reg::A1, 0); + i.call::<(), ()>("export_return_tuple_usize", ()).unwrap(); + assert_eq!(i.instance.reg(Reg::A0), a0); + assert_eq!(i.instance.reg(Reg::A1), a1); + } +} + fn basic_gas_metering(config: Config, gas_metering_kind: GasMeteringKind) { let _ = env_logger::try_init(); @@ -2859,7 +2888,8 @@ run_test_blob_tests! { test_blob_cmov_if_not_zero_with_zero_reg test_blob_min_stack_size test_blob_negate_and_add - test_blob_return_tuple + test_blob_return_tuple_from_import + test_blob_return_tuple_from_export } macro_rules! assert_impl { diff --git a/examples/doom/roms/doom.polkavm b/examples/doom/roms/doom.polkavm index 68c66d6b..ad9c3b96 100644 Binary files a/examples/doom/roms/doom.polkavm and b/examples/doom/roms/doom.polkavm differ diff --git a/guest-programs/Cargo.lock b/guest-programs/Cargo.lock index e5414c77..826ca1fd 100644 --- a/guest-programs/Cargo.lock +++ b/guest-programs/Cargo.lock @@ -92,7 +92,7 @@ dependencies = [ [[package]] name = "polkavm-derive-impl" -version = "0.18.0" +version = "0.18.1" dependencies = [ "polkavm-common", "proc-macro2", diff --git a/guest-programs/output/example-hello-world.polkavm b/guest-programs/output/example-hello-world.polkavm index ee843572..dfadeb2d 100644 Binary files a/guest-programs/output/example-hello-world.polkavm and b/guest-programs/output/example-hello-world.polkavm differ diff --git a/guest-programs/test-blob/src/main.rs b/guest-programs/test-blob/src/main.rs index 014ca12f..d32bb851 100644 --- a/guest-programs/test-blob/src/main.rs +++ b/guest-programs/test-blob/src/main.rs @@ -386,3 +386,28 @@ extern "C" fn test_return_tuple() { assert_eq!(unsafe { return_tuple_usize() }, (0x123456789abcdefe, 0x1122334455667788)); } } + +#[cfg(target_pointer_width = "32")] +#[polkavm_derive::polkavm_export] +extern "C" fn export_return_tuple_u32() -> (u32, u32) { + (0x12345678, 0x9abcdefe) +} + +#[cfg(target_pointer_width = "64")] +#[polkavm_derive::polkavm_export] +extern "C" fn export_return_tuple_u64() -> (u64, u64) { + (0x123456789abcdefe, 0x1122334455667788) +} + +#[polkavm_derive::polkavm_export] +extern "C" fn export_return_tuple_usize() -> (usize, usize) { + #[cfg(target_pointer_width = "32")] + { + (0x12345678, 0x9abcdefe) + } + + #[cfg(target_pointer_width = "64")] + { + (0x123456789abcdefe, 0x1122334455667788) + } +} diff --git a/test-data/test-blob_32.elf.zst b/test-data/test-blob_32.elf.zst index 6407bd64..07cfaed2 100644 Binary files a/test-data/test-blob_32.elf.zst and b/test-data/test-blob_32.elf.zst differ diff --git a/test-data/test-blob_64.elf.zst b/test-data/test-blob_64.elf.zst index 7f9177dc..e2dbfbb4 100644 Binary files a/test-data/test-blob_64.elf.zst and b/test-data/test-blob_64.elf.zst differ