mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-05 02:20:19 +00:00
Merge branch 'master' into fix-runtime-c-api-1314
This commit is contained in:
commit
2276d16f36
@ -3,6 +3,8 @@
|
||||
## **[Unreleased]**
|
||||
|
||||
- [#1335](https://github.com/wasmerio/wasmer/pull/1335) Change mutability of `memory` to `const` in `wasmer_memory_data_length` in the C API
|
||||
- [#1329](https://github.com/wasmerio/wasmer/pull/1329) New numbers and strings instructions for WIT
|
||||
- [#1332](https://github.com/wasmerio/wasmer/pull/1332) Add option to `CompilerConfig` to force compiler IR verification off even when `debug_assertions` are enabled. This can be used to make debug builds faster, which may be important if you're creating a library that wraps Wasmer and depend on the speed of debug builds.
|
||||
- [#1320](https://github.com/wasmerio/wasmer/pull/1320) Change `custom_sections` field in `ModuleInfo` to be more standards compliant by allowing multiple custom sections with the same name. To get the old behavior with the new API, you can add `.last().unwrap()` to accesses. For example, `module_info.custom_sections["custom_section_name"].last().unwrap()`.
|
||||
- [#1303](https://github.com/wasmerio/wasmer/pull/1303) NaN canonicalization for singlepass backend.
|
||||
- [#1292](https://github.com/wasmerio/wasmer/pull/1292) Experimental Support for Android (x86_64 and AArch64)
|
||||
|
@ -43,18 +43,27 @@ fn get_isa(config: Option<&CompilerConfig>) -> Box<dyn isa::TargetIsa> {
|
||||
builder.set("opt_level", "speed_and_size").unwrap();
|
||||
builder.set("enable_jump_tables", "false").unwrap();
|
||||
|
||||
if cfg!(test) || cfg!(debug_assertions) {
|
||||
builder.set("enable_verifier", "true").unwrap();
|
||||
} else {
|
||||
builder.set("enable_verifier", "false").unwrap();
|
||||
}
|
||||
let enable_verifier: bool;
|
||||
|
||||
if let Some(config) = config {
|
||||
if config.nan_canonicalization {
|
||||
builder.set("enable_nan_canonicalization", "true").unwrap();
|
||||
}
|
||||
enable_verifier = config.enable_verification;
|
||||
} else {
|
||||
// Set defaults if no config found.
|
||||
// NOTE: cfg(test) probably does nothing when not running `cargo test`
|
||||
// on this crate
|
||||
enable_verifier = cfg!(test) || cfg!(debug_assertions);
|
||||
}
|
||||
|
||||
builder
|
||||
.set(
|
||||
"enable_verifier",
|
||||
if enable_verifier { "true" } else { "false" },
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let flags = settings::Flags::new(builder);
|
||||
debug_assert_eq!(flags.opt_level(), settings::OptLevel::SpeedAndSize);
|
||||
flags
|
||||
|
@ -86,7 +86,7 @@ impl Trampolines {
|
||||
let sig_index = module.func_assoc[*exported_func_index];
|
||||
let func_sig = &module.signatures[sig_index];
|
||||
|
||||
let trampoline_func = generate_func(&func_sig);
|
||||
let trampoline_func = generate_func(isa, &func_sig);
|
||||
|
||||
ctx.func = trampoline_func;
|
||||
|
||||
@ -150,13 +150,13 @@ impl Trampolines {
|
||||
|
||||
/// This function generates a trampoline for the specific signature
|
||||
/// passed into it.
|
||||
fn generate_func(func_sig: &FuncSig) -> ir::Function {
|
||||
let trampoline_sig = generate_trampoline_signature();
|
||||
fn generate_func(isa: &dyn isa::TargetIsa, func_sig: &FuncSig) -> ir::Function {
|
||||
let trampoline_sig = generate_trampoline_signature(isa);
|
||||
|
||||
let mut func =
|
||||
ir::Function::with_name_signature(ir::ExternalName::testcase("trampln"), trampoline_sig);
|
||||
|
||||
let export_sig_ref = func.import_signature(generate_export_signature(func_sig));
|
||||
let export_sig_ref = func.import_signature(generate_export_signature(isa, func_sig));
|
||||
|
||||
let entry_ebb = func.dfg.make_block();
|
||||
let vmctx_ptr = func.dfg.append_block_param(entry_ebb, ir::types::I64);
|
||||
@ -211,8 +211,8 @@ fn wasm_ty_to_clif(ty: Type) -> ir::types::Type {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_trampoline_signature() -> ir::Signature {
|
||||
let call_convention = super::get_isa(None).default_call_conv();
|
||||
fn generate_trampoline_signature(isa: &dyn isa::TargetIsa) -> ir::Signature {
|
||||
let call_convention = isa.default_call_conv();
|
||||
let mut sig = ir::Signature::new(call_convention);
|
||||
|
||||
let ptr_param = ir::AbiParam {
|
||||
@ -227,8 +227,8 @@ fn generate_trampoline_signature() -> ir::Signature {
|
||||
sig
|
||||
}
|
||||
|
||||
fn generate_export_signature(func_sig: &FuncSig) -> ir::Signature {
|
||||
let call_convention = super::get_isa(None).default_call_conv();
|
||||
fn generate_export_signature(isa: &dyn isa::TargetIsa, func_sig: &FuncSig) -> ir::Signature {
|
||||
let call_convention = isa.default_call_conv();
|
||||
let mut export_clif_sig = ir::Signature::new(call_convention);
|
||||
|
||||
let func_sig_iter = func_sig.params().iter().map(|wasm_ty| ir::AbiParam {
|
||||
|
@ -41,57 +41,52 @@ binary.
|
||||
|
||||
## Instructions
|
||||
|
||||
Very basically, WebAssembly Interface Types defines a set of
|
||||
instructions, used by adapters to transform the data between
|
||||
WebAssembly core and the outside world ([learn
|
||||
Very basically, WebAssembly Interface Types defines a [set of
|
||||
instructions](https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/working-notes/Instructions.md),
|
||||
used by adapters to transform the data between WebAssembly core and
|
||||
the outside world ([learn
|
||||
mode](https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.md)).
|
||||
|
||||
Here is the instructions that are implemented:
|
||||
Here is the instructions that are implemented by this crate:
|
||||
|
||||
| Instruction | WAT encoder | Binary encoder | WAT decoder | Binary decoder | Interpreter |
|
||||
|-|-|-|-|-|-|
|
||||
| `arg.get` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `call-core` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `memory-to-string` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `string-to-memory` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `call-adapter` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||
| `defer-call-core` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||
| `i32-to-s8` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i32-to-s8x` | ✅ | ✅ | ✅ | ✅ | ❌ |
|
||||
| `i32-to-u8` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i32-to-s16` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i32-to-s16x` | ✅ | ✅ | ✅ | ✅ | ❌ |
|
||||
| `i32-to-u16` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i32-to-s32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i32-to-u32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i32-to-s64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i32-to-u64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i64-to-s8` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i64-to-s8x` | ✅ | ✅ | ✅ | ✅ | ❌ |
|
||||
| `i64-to-u8` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i64-to-s16` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i64-to-s16x` | ✅ | ✅ | ✅ | ✅ | ❌ |
|
||||
| `i64-to-u16` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i64-to-s32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i64-to-s32x` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i64-to-u32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i64-to-s64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `i64-to-u64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `s8-to-i32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `u8-to-i32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `s16-to-i32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `u16-to-i32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `s32-to-i32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `u32-to-i32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `s64-to-i32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `s64-to-i32x` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `u64-to-i32` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `u64-to-i32x` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `s8-to-i64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `u8-to-i64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `s16-to-i64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `u16-to-i64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `s32-to-i64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `u32-to-i64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `s64-to-i64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| `u64-to-i64` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Instruction | WAT encoder/decoder | Binary encoder/decoder | Interpreter | Comment |
|
||||
|-|-|-|-|-|
|
||||
| `arg.get` | ✅ | ✅ | ✅ | |
|
||||
| `call-core` | ✅ | ✅ | ✅ | |
|
||||
| `s8.from_i32` | ✅ | ✅ | ✅ | |
|
||||
| `s8.from_i64` | ✅ | ✅ | ✅ | |
|
||||
| `s16.from_i32` | ✅ | ✅ | ✅ | |
|
||||
| `s16.from_i64` | ✅ | ✅ | ✅ | |
|
||||
| `s32.from_i32` | ✅ | ✅ | ✅ | |
|
||||
| `s32.from_i64` | ✅ | ✅ | ✅ | |
|
||||
| `s64.from_i32` | ✅ | ✅ | ✅ | |
|
||||
| `s64.from_i64` | ✅ | ✅ | ✅ | |
|
||||
| `i32.from_s8` | ✅ | ✅ | ✅ | |
|
||||
| `i32.from_s16` | ✅ | ✅ | ✅ | |
|
||||
| `i32.from_s32` | ✅ | ✅ | ✅ | |
|
||||
| `i32.from_s64` | ✅ | ✅ | ✅ | |
|
||||
| `i64.from_s8` | ✅ | ✅ | ✅ | |
|
||||
| `i64.from_s16` | ✅ | ✅ | ✅ | |
|
||||
| `i64.from_s32` | ✅ | ✅ | ✅ | |
|
||||
| `i64.from_s64` | ✅ | ✅ | ✅ | |
|
||||
| `u8.from_i32` | ✅ | ✅ | ✅ | |
|
||||
| `u8.from_i64` | ✅ | ✅ | ✅ | |
|
||||
| `u16.from_i32` | ✅ | ✅ | ✅ | |
|
||||
| `u16.from_i64` | ✅ | ✅ | ✅ | |
|
||||
| `u32.from_i32` | ✅ | ✅ | ✅ | |
|
||||
| `u32.from_i64` | ✅ | ✅ | ✅ | |
|
||||
| `u64.from_i32` | ✅ | ✅ | ✅ | |
|
||||
| `u64.from_i64` | ✅ | ✅ | ✅ | |
|
||||
| `i32.from_u8` | ✅ | ✅ | ✅ | |
|
||||
| `i32.from_u16` | ✅ | ✅ | ✅ | |
|
||||
| `i32.from_u32` | ✅ | ✅ | ✅ | |
|
||||
| `i32.from_u64` | ✅ | ✅ | ✅ | |
|
||||
| `i64.from_u8` | ✅ | ✅ | ✅ | |
|
||||
| `i64.from_u16` | ✅ | ✅ | ✅ | |
|
||||
| `i64.from_u32` | ✅ | ✅ | ✅ | |
|
||||
| `i64.from_u64` | ✅ | ✅ | ✅ | |
|
||||
| `string.lift_memory` | ✅ | ✅ | ✅ | `#memidx` is not supported; `#encoding` is not supported but UTF-8 is assumed |
|
||||
| `string.lower_memory` | ✅ | ✅ | ✅ | `#memidx` is not supported; `#encoding` is not supported but UTF-8 is assumed |
|
||||
| `string.size` | ✅ | ✅ | ✅ | `#encoding` is not supported but UTF-8 is assumed |
|
||||
| `call-adapter` | ❌ | ❌ | ❌ | |
|
||||
| `defer-call-core` | ❌ | ❌ | ❌ | |
|
||||
|
@ -174,57 +174,52 @@ fn instruction<'input, E: ParseError<&'input [u8]>>(
|
||||
)
|
||||
}
|
||||
|
||||
0x03 => (input, Instruction::MemoryToString),
|
||||
0x02 => (input, Instruction::S8FromI32),
|
||||
0x03 => (input, Instruction::S8FromI64),
|
||||
0x04 => (input, Instruction::S16FromI32),
|
||||
0x05 => (input, Instruction::S16FromI64),
|
||||
0x06 => (input, Instruction::S32FromI32),
|
||||
0x07 => (input, Instruction::S32FromI64),
|
||||
0x08 => (input, Instruction::S64FromI32),
|
||||
0x09 => (input, Instruction::S64FromI64),
|
||||
0x0a => (input, Instruction::I32FromS8),
|
||||
0x0b => (input, Instruction::I32FromS16),
|
||||
0x0c => (input, Instruction::I32FromS32),
|
||||
0x0d => (input, Instruction::I32FromS64),
|
||||
0x0e => (input, Instruction::I64FromS8),
|
||||
0x0f => (input, Instruction::I64FromS16),
|
||||
0x10 => (input, Instruction::I64FromS32),
|
||||
0x11 => (input, Instruction::I64FromS64),
|
||||
0x12 => (input, Instruction::U8FromI32),
|
||||
0x13 => (input, Instruction::U8FromI64),
|
||||
0x14 => (input, Instruction::U16FromI32),
|
||||
0x15 => (input, Instruction::U16FromI64),
|
||||
0x16 => (input, Instruction::U32FromI32),
|
||||
0x17 => (input, Instruction::U32FromI64),
|
||||
0x18 => (input, Instruction::U64FromI32),
|
||||
0x19 => (input, Instruction::U64FromI64),
|
||||
0x1a => (input, Instruction::I32FromU8),
|
||||
0x1b => (input, Instruction::I32FromU16),
|
||||
0x1c => (input, Instruction::I32FromU32),
|
||||
0x1d => (input, Instruction::I32FromU64),
|
||||
0x1e => (input, Instruction::I64FromU8),
|
||||
0x1f => (input, Instruction::I64FromU16),
|
||||
0x20 => (input, Instruction::I64FromU32),
|
||||
0x21 => (input, Instruction::I64FromU64),
|
||||
|
||||
0x04 => {
|
||||
0x22 => (input, Instruction::StringLiftMemory),
|
||||
|
||||
0x23 => {
|
||||
consume!((input, argument_0) = uleb(input)?);
|
||||
(
|
||||
input,
|
||||
Instruction::StringToMemory {
|
||||
Instruction::StringLowerMemory {
|
||||
allocator_index: argument_0 as u32,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
0x07 => (input, Instruction::I32ToS8),
|
||||
0x08 => (input, Instruction::I32ToS8X),
|
||||
0x09 => (input, Instruction::I32ToU8),
|
||||
0x0a => (input, Instruction::I32ToS16),
|
||||
0x0b => (input, Instruction::I32ToS16X),
|
||||
0x0c => (input, Instruction::I32ToU16),
|
||||
0x0d => (input, Instruction::I32ToS32),
|
||||
0x0e => (input, Instruction::I32ToU32),
|
||||
0x0f => (input, Instruction::I32ToS64),
|
||||
0x10 => (input, Instruction::I32ToU64),
|
||||
0x11 => (input, Instruction::I64ToS8),
|
||||
0x12 => (input, Instruction::I64ToS8X),
|
||||
0x13 => (input, Instruction::I64ToU8),
|
||||
0x14 => (input, Instruction::I64ToS16),
|
||||
0x15 => (input, Instruction::I64ToS16X),
|
||||
0x16 => (input, Instruction::I64ToU16),
|
||||
0x17 => (input, Instruction::I64ToS32),
|
||||
0x18 => (input, Instruction::I64ToS32X),
|
||||
0x19 => (input, Instruction::I64ToU32),
|
||||
0x1a => (input, Instruction::I64ToS64),
|
||||
0x1b => (input, Instruction::I64ToU64),
|
||||
0x1c => (input, Instruction::S8ToI32),
|
||||
0x1d => (input, Instruction::U8ToI32),
|
||||
0x1e => (input, Instruction::S16ToI32),
|
||||
0x1f => (input, Instruction::U16ToI32),
|
||||
0x20 => (input, Instruction::S32ToI32),
|
||||
0x21 => (input, Instruction::U32ToI32),
|
||||
0x22 => (input, Instruction::S64ToI32),
|
||||
0x23 => (input, Instruction::S64ToI32X),
|
||||
0x24 => (input, Instruction::U64ToI32),
|
||||
0x25 => (input, Instruction::U64ToI32X),
|
||||
0x26 => (input, Instruction::S8ToI64),
|
||||
0x27 => (input, Instruction::U8ToI64),
|
||||
0x28 => (input, Instruction::S16ToI64),
|
||||
0x29 => (input, Instruction::U16ToI64),
|
||||
0x2a => (input, Instruction::S32ToI64),
|
||||
0x2b => (input, Instruction::U32ToI64),
|
||||
0x2c => (input, Instruction::S64ToI64),
|
||||
0x2d => (input, Instruction::U64ToI64),
|
||||
0x24 => (input, Instruction::StringSize),
|
||||
|
||||
_ => return Err(Err::Error(make_error(input, ErrorKind::ParseTo))),
|
||||
})
|
||||
@ -627,50 +622,44 @@ mod tests {
|
||||
#[test]
|
||||
fn test_instructions() {
|
||||
let input = &[
|
||||
0x2b, // list of 43 items
|
||||
0x25, // list of 37 items
|
||||
0x00, 0x01, // ArgumentGet { index: 1 }
|
||||
0x01, 0x01, // CallCore { function_index: 1 }
|
||||
0x03, // MemoryToString
|
||||
0x04, 0x01, // StringToMemory { allocator_index: 1 }
|
||||
0x07, // I32ToS8
|
||||
0x08, // I32ToS8X
|
||||
0x09, // I32ToU8
|
||||
0x0a, // I32ToS16
|
||||
0x0b, // I32ToS16X
|
||||
0x0c, // I32ToU16
|
||||
0x0d, // I32ToS32
|
||||
0x0e, // I32ToU32
|
||||
0x0f, // I32ToS64
|
||||
0x10, // I32ToU64
|
||||
0x11, // I64ToS8
|
||||
0x12, // I64ToS8X
|
||||
0x13, // I64ToU8
|
||||
0x14, // I64ToS16
|
||||
0x15, // I64ToS16X
|
||||
0x16, // I64ToU16
|
||||
0x17, // I64ToS32
|
||||
0x18, // I64ToS32X
|
||||
0x19, // I64ToU32
|
||||
0x1a, // I64ToS64
|
||||
0x1b, // I64ToU64
|
||||
0x1c, // S8ToI32
|
||||
0x1d, // U8ToI32
|
||||
0x1e, // S16ToI32
|
||||
0x1f, // U16ToI32
|
||||
0x20, // S32ToI32
|
||||
0x21, // U32ToI32
|
||||
0x22, // S64ToI32
|
||||
0x23, // S64ToI32X
|
||||
0x24, // U64ToI32
|
||||
0x25, // U64ToI32X
|
||||
0x26, // S8ToI64
|
||||
0x27, // U8ToI64
|
||||
0x28, // S16ToI64
|
||||
0x29, // U16ToI64
|
||||
0x2a, // S32ToI64
|
||||
0x2b, // U32ToI64
|
||||
0x2c, // S64ToI64
|
||||
0x2d, // U64ToI64
|
||||
0x02, // S8FromI32
|
||||
0x03, // S8FromI64
|
||||
0x04, // S16FromI32
|
||||
0x05, // S16FromI64
|
||||
0x06, // S32FromI32
|
||||
0x07, // S32FromI64
|
||||
0x08, // S64FromI32
|
||||
0x09, // S64FromI64
|
||||
0x0a, // I32FromS8
|
||||
0x0b, // I32FromS16
|
||||
0x0c, // I32FromS32
|
||||
0x0d, // I32FromS64
|
||||
0x0e, // I64FromS8
|
||||
0x0f, // I64FromS16
|
||||
0x10, // I64FromS32
|
||||
0x11, // I64FromS64
|
||||
0x12, // U8FromI32
|
||||
0x13, // U8FromI64
|
||||
0x14, // U16FromI32
|
||||
0x15, // U16FromI64
|
||||
0x16, // U32FromI32
|
||||
0x17, // U32FromI64
|
||||
0x18, // U64FromI32
|
||||
0x19, // U64FromI64
|
||||
0x1a, // I32FromU8
|
||||
0x1b, // I32FromU16
|
||||
0x1c, // I32FromU32
|
||||
0x1d, // I32FromU64
|
||||
0x1e, // I64FromU8
|
||||
0x1f, // I64FromU16
|
||||
0x20, // I64FromU32
|
||||
0x21, // I64FromU64
|
||||
0x22, // StringLiftMemory
|
||||
0x23, 0x01, // StringLowerMemory { allocator_index: 1 }
|
||||
0x24, // StringSize
|
||||
0x0a,
|
||||
];
|
||||
let output = Ok((
|
||||
@ -678,47 +667,41 @@ mod tests {
|
||||
vec![
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::CallCore { function_index: 1 },
|
||||
Instruction::MemoryToString,
|
||||
Instruction::StringToMemory { allocator_index: 1 },
|
||||
Instruction::I32ToS8,
|
||||
Instruction::I32ToS8X,
|
||||
Instruction::I32ToU8,
|
||||
Instruction::I32ToS16,
|
||||
Instruction::I32ToS16X,
|
||||
Instruction::I32ToU16,
|
||||
Instruction::I32ToS32,
|
||||
Instruction::I32ToU32,
|
||||
Instruction::I32ToS64,
|
||||
Instruction::I32ToU64,
|
||||
Instruction::I64ToS8,
|
||||
Instruction::I64ToS8X,
|
||||
Instruction::I64ToU8,
|
||||
Instruction::I64ToS16,
|
||||
Instruction::I64ToS16X,
|
||||
Instruction::I64ToU16,
|
||||
Instruction::I64ToS32,
|
||||
Instruction::I64ToS32X,
|
||||
Instruction::I64ToU32,
|
||||
Instruction::I64ToS64,
|
||||
Instruction::I64ToU64,
|
||||
Instruction::S8ToI32,
|
||||
Instruction::U8ToI32,
|
||||
Instruction::S16ToI32,
|
||||
Instruction::U16ToI32,
|
||||
Instruction::S32ToI32,
|
||||
Instruction::U32ToI32,
|
||||
Instruction::S64ToI32,
|
||||
Instruction::S64ToI32X,
|
||||
Instruction::U64ToI32,
|
||||
Instruction::U64ToI32X,
|
||||
Instruction::S8ToI64,
|
||||
Instruction::U8ToI64,
|
||||
Instruction::S16ToI64,
|
||||
Instruction::U16ToI64,
|
||||
Instruction::S32ToI64,
|
||||
Instruction::U32ToI64,
|
||||
Instruction::S64ToI64,
|
||||
Instruction::U64ToI64,
|
||||
Instruction::S8FromI32,
|
||||
Instruction::S8FromI64,
|
||||
Instruction::S16FromI32,
|
||||
Instruction::S16FromI64,
|
||||
Instruction::S32FromI32,
|
||||
Instruction::S32FromI64,
|
||||
Instruction::S64FromI32,
|
||||
Instruction::S64FromI64,
|
||||
Instruction::I32FromS8,
|
||||
Instruction::I32FromS16,
|
||||
Instruction::I32FromS32,
|
||||
Instruction::I32FromS64,
|
||||
Instruction::I64FromS8,
|
||||
Instruction::I64FromS16,
|
||||
Instruction::I64FromS32,
|
||||
Instruction::I64FromS64,
|
||||
Instruction::U8FromI32,
|
||||
Instruction::U8FromI64,
|
||||
Instruction::U16FromI32,
|
||||
Instruction::U16FromI64,
|
||||
Instruction::U32FromI32,
|
||||
Instruction::U32FromI64,
|
||||
Instruction::U64FromI32,
|
||||
Instruction::U64FromI64,
|
||||
Instruction::I32FromU8,
|
||||
Instruction::I32FromU16,
|
||||
Instruction::I32FromU32,
|
||||
Instruction::I32FromU64,
|
||||
Instruction::I64FromU8,
|
||||
Instruction::I64FromU16,
|
||||
Instruction::I64FromU32,
|
||||
Instruction::I64FromU64,
|
||||
Instruction::StringLiftMemory,
|
||||
Instruction::StringLowerMemory { allocator_index: 1 },
|
||||
Instruction::StringSize,
|
||||
],
|
||||
));
|
||||
|
||||
|
@ -28,47 +28,41 @@ mod keyword {
|
||||
// Instructions.
|
||||
custom_keyword!(argument_get = "arg.get");
|
||||
custom_keyword!(call_core = "call-core");
|
||||
custom_keyword!(memory_to_string = "memory-to-string");
|
||||
custom_keyword!(string_to_memory = "string-to-memory");
|
||||
custom_keyword!(i32_to_s8 = "i32-to-s8");
|
||||
custom_keyword!(i32_to_s8x = "i32-to-s8x");
|
||||
custom_keyword!(i32_to_u8 = "i32-to-u8");
|
||||
custom_keyword!(i32_to_s16 = "i32-to-s16");
|
||||
custom_keyword!(i32_to_s16x = "i32-to-s16x");
|
||||
custom_keyword!(i32_to_u16 = "i32-to-u16");
|
||||
custom_keyword!(i32_to_s32 = "i32-to-s32");
|
||||
custom_keyword!(i32_to_u32 = "i32-to-u32");
|
||||
custom_keyword!(i32_to_s64 = "i32-to-s64");
|
||||
custom_keyword!(i32_to_u64 = "i32-to-u64");
|
||||
custom_keyword!(i64_to_s8 = "i64-to-s8");
|
||||
custom_keyword!(i64_to_s8x = "i64-to-s8x");
|
||||
custom_keyword!(i64_to_u8 = "i64-to-u8");
|
||||
custom_keyword!(i64_to_s16 = "i64-to-s16");
|
||||
custom_keyword!(i64_to_s16x = "i64-to-s16x");
|
||||
custom_keyword!(i64_to_u16 = "i64-to-u16");
|
||||
custom_keyword!(i64_to_s32 = "i64-to-s32");
|
||||
custom_keyword!(i64_to_s32x = "i64-to-s32x");
|
||||
custom_keyword!(i64_to_u32 = "i64-to-u32");
|
||||
custom_keyword!(i64_to_s64 = "i64-to-s64");
|
||||
custom_keyword!(i64_to_u64 = "i64-to-u64");
|
||||
custom_keyword!(s8_to_i32 = "s8-to-i32");
|
||||
custom_keyword!(u8_to_i32 = "u8-to-i32");
|
||||
custom_keyword!(s16_to_i32 = "s16-to-i32");
|
||||
custom_keyword!(u16_to_i32 = "u16-to-i32");
|
||||
custom_keyword!(s32_to_i32 = "s32-to-i32");
|
||||
custom_keyword!(u32_to_i32 = "u32-to-i32");
|
||||
custom_keyword!(s64_to_i32 = "s64-to-i32");
|
||||
custom_keyword!(s64_to_i32x = "s64-to-i32x");
|
||||
custom_keyword!(u64_to_i32 = "u64-to-i32");
|
||||
custom_keyword!(u64_to_i32x = "u64-to-i32x");
|
||||
custom_keyword!(s8_to_i64 = "s8-to-i64");
|
||||
custom_keyword!(u8_to_i64 = "u8-to-i64");
|
||||
custom_keyword!(s16_to_i64 = "s16-to-i64");
|
||||
custom_keyword!(u16_to_i64 = "u16-to-i64");
|
||||
custom_keyword!(s32_to_i64 = "s32-to-i64");
|
||||
custom_keyword!(u32_to_i64 = "u32-to-i64");
|
||||
custom_keyword!(s64_to_i64 = "s64-to-i64");
|
||||
custom_keyword!(u64_to_i64 = "u64-to-i64");
|
||||
custom_keyword!(s8_from_i32 = "s8.from_i32");
|
||||
custom_keyword!(s8_from_i64 = "s8.from_i64");
|
||||
custom_keyword!(s16_from_i32 = "s16.from_i32");
|
||||
custom_keyword!(s16_from_i64 = "s16.from_i64");
|
||||
custom_keyword!(s32_from_i32 = "s32.from_i32");
|
||||
custom_keyword!(s32_from_i64 = "s32.from_i64");
|
||||
custom_keyword!(s64_from_i32 = "s64.from_i32");
|
||||
custom_keyword!(s64_from_i64 = "s64.from_i64");
|
||||
custom_keyword!(i32_from_s8 = "i32.from_s8");
|
||||
custom_keyword!(i32_from_s16 = "i32.from_s16");
|
||||
custom_keyword!(i32_from_s32 = "i32.from_s32");
|
||||
custom_keyword!(i32_from_s64 = "i32.from_s64");
|
||||
custom_keyword!(i64_from_s8 = "i64.from_s8");
|
||||
custom_keyword!(i64_from_s16 = "i64.from_s16");
|
||||
custom_keyword!(i64_from_s32 = "i64.from_s32");
|
||||
custom_keyword!(i64_from_s64 = "i64.from_s64");
|
||||
custom_keyword!(u8_from_i32 = "u8.from_i32");
|
||||
custom_keyword!(u8_from_i64 = "u8.from_i64");
|
||||
custom_keyword!(u16_from_i32 = "u16.from_i32");
|
||||
custom_keyword!(u16_from_i64 = "u16.from_i64");
|
||||
custom_keyword!(u32_from_i32 = "u32.from_i32");
|
||||
custom_keyword!(u32_from_i64 = "u32.from_i64");
|
||||
custom_keyword!(u64_from_i32 = "u64.from_i32");
|
||||
custom_keyword!(u64_from_i64 = "u64.from_i64");
|
||||
custom_keyword!(i32_from_u8 = "i32.from_u8");
|
||||
custom_keyword!(i32_from_u16 = "i32.from_u16");
|
||||
custom_keyword!(i32_from_u32 = "i32.from_u32");
|
||||
custom_keyword!(i32_from_u64 = "i32.from_u64");
|
||||
custom_keyword!(i64_from_u8 = "i64.from_u8");
|
||||
custom_keyword!(i64_from_u16 = "i64.from_u16");
|
||||
custom_keyword!(i64_from_u32 = "i64.from_u32");
|
||||
custom_keyword!(i64_from_u64 = "i64.from_u64");
|
||||
custom_keyword!(string_lift_memory = "string.lift_memory");
|
||||
custom_keyword!(string_lower_memory = "string.lower_memory");
|
||||
custom_keyword!(string_size = "string.size");
|
||||
}
|
||||
|
||||
impl Parse<'_> for InterfaceType {
|
||||
@ -154,172 +148,148 @@ impl<'a> Parse<'a> for Instruction {
|
||||
Ok(Instruction::CallCore {
|
||||
function_index: parser.parse::<u64>()? as usize,
|
||||
})
|
||||
} else if lookahead.peek::<keyword::memory_to_string>() {
|
||||
parser.parse::<keyword::memory_to_string>()?;
|
||||
} else if lookahead.peek::<keyword::s8_from_i32>() {
|
||||
parser.parse::<keyword::s8_from_i32>()?;
|
||||
|
||||
Ok(Instruction::MemoryToString)
|
||||
} else if lookahead.peek::<keyword::string_to_memory>() {
|
||||
parser.parse::<keyword::string_to_memory>()?;
|
||||
Ok(Instruction::S8FromI32)
|
||||
} else if lookahead.peek::<keyword::s8_from_i64>() {
|
||||
parser.parse::<keyword::s8_from_i64>()?;
|
||||
|
||||
Ok(Instruction::StringToMemory {
|
||||
Ok(Instruction::S8FromI64)
|
||||
} else if lookahead.peek::<keyword::s16_from_i32>() {
|
||||
parser.parse::<keyword::s16_from_i32>()?;
|
||||
|
||||
Ok(Instruction::S16FromI32)
|
||||
} else if lookahead.peek::<keyword::s16_from_i64>() {
|
||||
parser.parse::<keyword::s16_from_i64>()?;
|
||||
|
||||
Ok(Instruction::S16FromI64)
|
||||
} else if lookahead.peek::<keyword::s32_from_i32>() {
|
||||
parser.parse::<keyword::s32_from_i32>()?;
|
||||
|
||||
Ok(Instruction::S32FromI32)
|
||||
} else if lookahead.peek::<keyword::s32_from_i64>() {
|
||||
parser.parse::<keyword::s32_from_i64>()?;
|
||||
|
||||
Ok(Instruction::S32FromI64)
|
||||
} else if lookahead.peek::<keyword::s64_from_i32>() {
|
||||
parser.parse::<keyword::s64_from_i32>()?;
|
||||
|
||||
Ok(Instruction::S64FromI32)
|
||||
} else if lookahead.peek::<keyword::s64_from_i64>() {
|
||||
parser.parse::<keyword::s64_from_i64>()?;
|
||||
|
||||
Ok(Instruction::S64FromI64)
|
||||
} else if lookahead.peek::<keyword::i32_from_s8>() {
|
||||
parser.parse::<keyword::i32_from_s8>()?;
|
||||
|
||||
Ok(Instruction::I32FromS8)
|
||||
} else if lookahead.peek::<keyword::i32_from_s16>() {
|
||||
parser.parse::<keyword::i32_from_s16>()?;
|
||||
|
||||
Ok(Instruction::I32FromS16)
|
||||
} else if lookahead.peek::<keyword::i32_from_s32>() {
|
||||
parser.parse::<keyword::i32_from_s32>()?;
|
||||
|
||||
Ok(Instruction::I32FromS32)
|
||||
} else if lookahead.peek::<keyword::i32_from_s64>() {
|
||||
parser.parse::<keyword::i32_from_s64>()?;
|
||||
|
||||
Ok(Instruction::I32FromS64)
|
||||
} else if lookahead.peek::<keyword::i64_from_s8>() {
|
||||
parser.parse::<keyword::i64_from_s8>()?;
|
||||
|
||||
Ok(Instruction::I64FromS8)
|
||||
} else if lookahead.peek::<keyword::i64_from_s16>() {
|
||||
parser.parse::<keyword::i64_from_s16>()?;
|
||||
|
||||
Ok(Instruction::I64FromS16)
|
||||
} else if lookahead.peek::<keyword::i64_from_s32>() {
|
||||
parser.parse::<keyword::i64_from_s32>()?;
|
||||
|
||||
Ok(Instruction::I64FromS32)
|
||||
} else if lookahead.peek::<keyword::i64_from_s64>() {
|
||||
parser.parse::<keyword::i64_from_s64>()?;
|
||||
|
||||
Ok(Instruction::I64FromS64)
|
||||
} else if lookahead.peek::<keyword::u8_from_i32>() {
|
||||
parser.parse::<keyword::u8_from_i32>()?;
|
||||
|
||||
Ok(Instruction::U8FromI32)
|
||||
} else if lookahead.peek::<keyword::u8_from_i64>() {
|
||||
parser.parse::<keyword::u8_from_i64>()?;
|
||||
|
||||
Ok(Instruction::U8FromI64)
|
||||
} else if lookahead.peek::<keyword::u16_from_i32>() {
|
||||
parser.parse::<keyword::u16_from_i32>()?;
|
||||
|
||||
Ok(Instruction::U16FromI32)
|
||||
} else if lookahead.peek::<keyword::u16_from_i64>() {
|
||||
parser.parse::<keyword::u16_from_i64>()?;
|
||||
|
||||
Ok(Instruction::U16FromI64)
|
||||
} else if lookahead.peek::<keyword::u32_from_i32>() {
|
||||
parser.parse::<keyword::u32_from_i32>()?;
|
||||
|
||||
Ok(Instruction::U32FromI32)
|
||||
} else if lookahead.peek::<keyword::u32_from_i64>() {
|
||||
parser.parse::<keyword::u32_from_i64>()?;
|
||||
|
||||
Ok(Instruction::U32FromI64)
|
||||
} else if lookahead.peek::<keyword::u64_from_i32>() {
|
||||
parser.parse::<keyword::u64_from_i32>()?;
|
||||
|
||||
Ok(Instruction::U64FromI32)
|
||||
} else if lookahead.peek::<keyword::u64_from_i64>() {
|
||||
parser.parse::<keyword::u64_from_i64>()?;
|
||||
|
||||
Ok(Instruction::U64FromI64)
|
||||
} else if lookahead.peek::<keyword::i32_from_u8>() {
|
||||
parser.parse::<keyword::i32_from_u8>()?;
|
||||
|
||||
Ok(Instruction::I32FromU8)
|
||||
} else if lookahead.peek::<keyword::i32_from_u16>() {
|
||||
parser.parse::<keyword::i32_from_u16>()?;
|
||||
|
||||
Ok(Instruction::I32FromU16)
|
||||
} else if lookahead.peek::<keyword::i32_from_u32>() {
|
||||
parser.parse::<keyword::i32_from_u32>()?;
|
||||
|
||||
Ok(Instruction::I32FromU32)
|
||||
} else if lookahead.peek::<keyword::i32_from_u64>() {
|
||||
parser.parse::<keyword::i32_from_u64>()?;
|
||||
|
||||
Ok(Instruction::I32FromU64)
|
||||
} else if lookahead.peek::<keyword::i64_from_u8>() {
|
||||
parser.parse::<keyword::i64_from_u8>()?;
|
||||
|
||||
Ok(Instruction::I64FromU8)
|
||||
} else if lookahead.peek::<keyword::i64_from_u16>() {
|
||||
parser.parse::<keyword::i64_from_u16>()?;
|
||||
|
||||
Ok(Instruction::I64FromU16)
|
||||
} else if lookahead.peek::<keyword::i64_from_u32>() {
|
||||
parser.parse::<keyword::i64_from_u32>()?;
|
||||
|
||||
Ok(Instruction::I64FromU32)
|
||||
} else if lookahead.peek::<keyword::i64_from_u64>() {
|
||||
parser.parse::<keyword::i64_from_u64>()?;
|
||||
|
||||
Ok(Instruction::I64FromU64)
|
||||
} else if lookahead.peek::<keyword::string_lift_memory>() {
|
||||
parser.parse::<keyword::string_lift_memory>()?;
|
||||
|
||||
Ok(Instruction::StringLiftMemory)
|
||||
} else if lookahead.peek::<keyword::string_lower_memory>() {
|
||||
parser.parse::<keyword::string_lower_memory>()?;
|
||||
|
||||
Ok(Instruction::StringLowerMemory {
|
||||
allocator_index: parser.parse()?,
|
||||
})
|
||||
} else if lookahead.peek::<keyword::i32_to_s8>() {
|
||||
parser.parse::<keyword::i32_to_s8>()?;
|
||||
} else if lookahead.peek::<keyword::string_size>() {
|
||||
parser.parse::<keyword::string_size>()?;
|
||||
|
||||
Ok(Instruction::I32ToS8)
|
||||
} else if lookahead.peek::<keyword::i32_to_s8x>() {
|
||||
parser.parse::<keyword::i32_to_s8x>()?;
|
||||
|
||||
Ok(Instruction::I32ToS8X)
|
||||
} else if lookahead.peek::<keyword::i32_to_u8>() {
|
||||
parser.parse::<keyword::i32_to_u8>()?;
|
||||
|
||||
Ok(Instruction::I32ToU8)
|
||||
} else if lookahead.peek::<keyword::i32_to_s16>() {
|
||||
parser.parse::<keyword::i32_to_s16>()?;
|
||||
|
||||
Ok(Instruction::I32ToS16)
|
||||
} else if lookahead.peek::<keyword::i32_to_s16x>() {
|
||||
parser.parse::<keyword::i32_to_s16x>()?;
|
||||
|
||||
Ok(Instruction::I32ToS16X)
|
||||
} else if lookahead.peek::<keyword::i32_to_u16>() {
|
||||
parser.parse::<keyword::i32_to_u16>()?;
|
||||
|
||||
Ok(Instruction::I32ToU16)
|
||||
} else if lookahead.peek::<keyword::i32_to_s32>() {
|
||||
parser.parse::<keyword::i32_to_s32>()?;
|
||||
|
||||
Ok(Instruction::I32ToS32)
|
||||
} else if lookahead.peek::<keyword::i32_to_u32>() {
|
||||
parser.parse::<keyword::i32_to_u32>()?;
|
||||
|
||||
Ok(Instruction::I32ToU32)
|
||||
} else if lookahead.peek::<keyword::i32_to_s64>() {
|
||||
parser.parse::<keyword::i32_to_s64>()?;
|
||||
|
||||
Ok(Instruction::I32ToS64)
|
||||
} else if lookahead.peek::<keyword::i32_to_u64>() {
|
||||
parser.parse::<keyword::i32_to_u64>()?;
|
||||
|
||||
Ok(Instruction::I32ToU64)
|
||||
} else if lookahead.peek::<keyword::i64_to_s8>() {
|
||||
parser.parse::<keyword::i64_to_s8>()?;
|
||||
|
||||
Ok(Instruction::I64ToS8)
|
||||
} else if lookahead.peek::<keyword::i64_to_s8x>() {
|
||||
parser.parse::<keyword::i64_to_s8x>()?;
|
||||
|
||||
Ok(Instruction::I64ToS8X)
|
||||
} else if lookahead.peek::<keyword::i64_to_u8>() {
|
||||
parser.parse::<keyword::i64_to_u8>()?;
|
||||
|
||||
Ok(Instruction::I64ToU8)
|
||||
} else if lookahead.peek::<keyword::i64_to_s16>() {
|
||||
parser.parse::<keyword::i64_to_s16>()?;
|
||||
|
||||
Ok(Instruction::I64ToS16)
|
||||
} else if lookahead.peek::<keyword::i64_to_s16x>() {
|
||||
parser.parse::<keyword::i64_to_s16x>()?;
|
||||
|
||||
Ok(Instruction::I64ToS16X)
|
||||
} else if lookahead.peek::<keyword::i64_to_u16>() {
|
||||
parser.parse::<keyword::i64_to_u16>()?;
|
||||
|
||||
Ok(Instruction::I64ToU16)
|
||||
} else if lookahead.peek::<keyword::i64_to_s32>() {
|
||||
parser.parse::<keyword::i64_to_s32>()?;
|
||||
|
||||
Ok(Instruction::I64ToS32)
|
||||
} else if lookahead.peek::<keyword::i64_to_s32x>() {
|
||||
parser.parse::<keyword::i64_to_s32x>()?;
|
||||
|
||||
Ok(Instruction::I64ToS32X)
|
||||
} else if lookahead.peek::<keyword::i64_to_u32>() {
|
||||
parser.parse::<keyword::i64_to_u32>()?;
|
||||
|
||||
Ok(Instruction::I64ToU32)
|
||||
} else if lookahead.peek::<keyword::i64_to_s64>() {
|
||||
parser.parse::<keyword::i64_to_s64>()?;
|
||||
|
||||
Ok(Instruction::I64ToS64)
|
||||
} else if lookahead.peek::<keyword::i64_to_u64>() {
|
||||
parser.parse::<keyword::i64_to_u64>()?;
|
||||
|
||||
Ok(Instruction::I64ToU64)
|
||||
} else if lookahead.peek::<keyword::s8_to_i32>() {
|
||||
parser.parse::<keyword::s8_to_i32>()?;
|
||||
|
||||
Ok(Instruction::S8ToI32)
|
||||
} else if lookahead.peek::<keyword::u8_to_i32>() {
|
||||
parser.parse::<keyword::u8_to_i32>()?;
|
||||
|
||||
Ok(Instruction::U8ToI32)
|
||||
} else if lookahead.peek::<keyword::s16_to_i32>() {
|
||||
parser.parse::<keyword::s16_to_i32>()?;
|
||||
|
||||
Ok(Instruction::S16ToI32)
|
||||
} else if lookahead.peek::<keyword::u16_to_i32>() {
|
||||
parser.parse::<keyword::u16_to_i32>()?;
|
||||
|
||||
Ok(Instruction::U16ToI32)
|
||||
} else if lookahead.peek::<keyword::s32_to_i32>() {
|
||||
parser.parse::<keyword::s32_to_i32>()?;
|
||||
|
||||
Ok(Instruction::S32ToI32)
|
||||
} else if lookahead.peek::<keyword::u32_to_i32>() {
|
||||
parser.parse::<keyword::u32_to_i32>()?;
|
||||
|
||||
Ok(Instruction::U32ToI32)
|
||||
} else if lookahead.peek::<keyword::s64_to_i32>() {
|
||||
parser.parse::<keyword::s64_to_i32>()?;
|
||||
|
||||
Ok(Instruction::S64ToI32)
|
||||
} else if lookahead.peek::<keyword::s64_to_i32x>() {
|
||||
parser.parse::<keyword::s64_to_i32x>()?;
|
||||
|
||||
Ok(Instruction::S64ToI32X)
|
||||
} else if lookahead.peek::<keyword::u64_to_i32>() {
|
||||
parser.parse::<keyword::u64_to_i32>()?;
|
||||
|
||||
Ok(Instruction::U64ToI32)
|
||||
} else if lookahead.peek::<keyword::u64_to_i32x>() {
|
||||
parser.parse::<keyword::u64_to_i32x>()?;
|
||||
|
||||
Ok(Instruction::U64ToI32X)
|
||||
} else if lookahead.peek::<keyword::s8_to_i64>() {
|
||||
parser.parse::<keyword::s8_to_i64>()?;
|
||||
|
||||
Ok(Instruction::S8ToI64)
|
||||
} else if lookahead.peek::<keyword::u8_to_i64>() {
|
||||
parser.parse::<keyword::u8_to_i64>()?;
|
||||
|
||||
Ok(Instruction::U8ToI64)
|
||||
} else if lookahead.peek::<keyword::s16_to_i64>() {
|
||||
parser.parse::<keyword::s16_to_i64>()?;
|
||||
|
||||
Ok(Instruction::S16ToI64)
|
||||
} else if lookahead.peek::<keyword::u16_to_i64>() {
|
||||
parser.parse::<keyword::u16_to_i64>()?;
|
||||
|
||||
Ok(Instruction::U16ToI64)
|
||||
} else if lookahead.peek::<keyword::s32_to_i64>() {
|
||||
parser.parse::<keyword::s32_to_i64>()?;
|
||||
|
||||
Ok(Instruction::S32ToI64)
|
||||
} else if lookahead.peek::<keyword::u32_to_i64>() {
|
||||
parser.parse::<keyword::u32_to_i64>()?;
|
||||
|
||||
Ok(Instruction::U32ToI64)
|
||||
} else if lookahead.peek::<keyword::s64_to_i64>() {
|
||||
parser.parse::<keyword::s64_to_i64>()?;
|
||||
|
||||
Ok(Instruction::S64ToI64)
|
||||
} else if lookahead.peek::<keyword::u64_to_i64>() {
|
||||
parser.parse::<keyword::u64_to_i64>()?;
|
||||
|
||||
Ok(Instruction::U64ToI64)
|
||||
Ok(Instruction::StringSize)
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
@ -667,94 +637,82 @@ mod tests {
|
||||
let inputs = vec![
|
||||
"arg.get 7",
|
||||
"call-core 7",
|
||||
"memory-to-string",
|
||||
"string-to-memory 42",
|
||||
"i32-to-s8",
|
||||
"i32-to-s8x",
|
||||
"i32-to-u8",
|
||||
"i32-to-s16",
|
||||
"i32-to-s16x",
|
||||
"i32-to-u16",
|
||||
"i32-to-s32",
|
||||
"i32-to-u32",
|
||||
"i32-to-s64",
|
||||
"i32-to-u64",
|
||||
"i64-to-s8",
|
||||
"i64-to-s8x",
|
||||
"i64-to-u8",
|
||||
"i64-to-s16",
|
||||
"i64-to-s16x",
|
||||
"i64-to-u16",
|
||||
"i64-to-s32",
|
||||
"i64-to-s32x",
|
||||
"i64-to-u32",
|
||||
"i64-to-s64",
|
||||
"i64-to-u64",
|
||||
"s8-to-i32",
|
||||
"u8-to-i32",
|
||||
"s16-to-i32",
|
||||
"u16-to-i32",
|
||||
"s32-to-i32",
|
||||
"u32-to-i32",
|
||||
"s64-to-i32",
|
||||
"s64-to-i32x",
|
||||
"u64-to-i32",
|
||||
"u64-to-i32x",
|
||||
"s8-to-i64",
|
||||
"u8-to-i64",
|
||||
"s16-to-i64",
|
||||
"u16-to-i64",
|
||||
"s32-to-i64",
|
||||
"u32-to-i64",
|
||||
"s64-to-i64",
|
||||
"u64-to-i64",
|
||||
"s8.from_i32",
|
||||
"s8.from_i64",
|
||||
"s16.from_i32",
|
||||
"s16.from_i64",
|
||||
"s32.from_i32",
|
||||
"s32.from_i64",
|
||||
"s64.from_i32",
|
||||
"s64.from_i64",
|
||||
"i32.from_s8",
|
||||
"i32.from_s16",
|
||||
"i32.from_s32",
|
||||
"i32.from_s64",
|
||||
"i64.from_s8",
|
||||
"i64.from_s16",
|
||||
"i64.from_s32",
|
||||
"i64.from_s64",
|
||||
"u8.from_i32",
|
||||
"u8.from_i64",
|
||||
"u16.from_i32",
|
||||
"u16.from_i64",
|
||||
"u32.from_i32",
|
||||
"u32.from_i64",
|
||||
"u64.from_i32",
|
||||
"u64.from_i64",
|
||||
"i32.from_u8",
|
||||
"i32.from_u16",
|
||||
"i32.from_u32",
|
||||
"i32.from_u64",
|
||||
"i64.from_u8",
|
||||
"i64.from_u16",
|
||||
"i64.from_u32",
|
||||
"i64.from_u64",
|
||||
"string.lift_memory",
|
||||
"string.lower_memory 42",
|
||||
"string.size",
|
||||
];
|
||||
let outputs = vec![
|
||||
Instruction::ArgumentGet { index: 7 },
|
||||
Instruction::CallCore { function_index: 7 },
|
||||
Instruction::MemoryToString,
|
||||
Instruction::StringToMemory {
|
||||
Instruction::S8FromI32,
|
||||
Instruction::S8FromI64,
|
||||
Instruction::S16FromI32,
|
||||
Instruction::S16FromI64,
|
||||
Instruction::S32FromI32,
|
||||
Instruction::S32FromI64,
|
||||
Instruction::S64FromI32,
|
||||
Instruction::S64FromI64,
|
||||
Instruction::I32FromS8,
|
||||
Instruction::I32FromS16,
|
||||
Instruction::I32FromS32,
|
||||
Instruction::I32FromS64,
|
||||
Instruction::I64FromS8,
|
||||
Instruction::I64FromS16,
|
||||
Instruction::I64FromS32,
|
||||
Instruction::I64FromS64,
|
||||
Instruction::U8FromI32,
|
||||
Instruction::U8FromI64,
|
||||
Instruction::U16FromI32,
|
||||
Instruction::U16FromI64,
|
||||
Instruction::U32FromI32,
|
||||
Instruction::U32FromI64,
|
||||
Instruction::U64FromI32,
|
||||
Instruction::U64FromI64,
|
||||
Instruction::I32FromU8,
|
||||
Instruction::I32FromU16,
|
||||
Instruction::I32FromU32,
|
||||
Instruction::I32FromU64,
|
||||
Instruction::I64FromU8,
|
||||
Instruction::I64FromU16,
|
||||
Instruction::I64FromU32,
|
||||
Instruction::I64FromU64,
|
||||
Instruction::StringLiftMemory,
|
||||
Instruction::StringLowerMemory {
|
||||
allocator_index: 42,
|
||||
},
|
||||
Instruction::I32ToS8,
|
||||
Instruction::I32ToS8X,
|
||||
Instruction::I32ToU8,
|
||||
Instruction::I32ToS16,
|
||||
Instruction::I32ToS16X,
|
||||
Instruction::I32ToU16,
|
||||
Instruction::I32ToS32,
|
||||
Instruction::I32ToU32,
|
||||
Instruction::I32ToS64,
|
||||
Instruction::I32ToU64,
|
||||
Instruction::I64ToS8,
|
||||
Instruction::I64ToS8X,
|
||||
Instruction::I64ToU8,
|
||||
Instruction::I64ToS16,
|
||||
Instruction::I64ToS16X,
|
||||
Instruction::I64ToU16,
|
||||
Instruction::I64ToS32,
|
||||
Instruction::I64ToS32X,
|
||||
Instruction::I64ToU32,
|
||||
Instruction::I64ToS64,
|
||||
Instruction::I64ToU64,
|
||||
Instruction::S8ToI32,
|
||||
Instruction::U8ToI32,
|
||||
Instruction::S16ToI32,
|
||||
Instruction::U16ToI32,
|
||||
Instruction::S32ToI32,
|
||||
Instruction::U32ToI32,
|
||||
Instruction::S64ToI32,
|
||||
Instruction::S64ToI32X,
|
||||
Instruction::U64ToI32,
|
||||
Instruction::U64ToI32X,
|
||||
Instruction::S8ToI64,
|
||||
Instruction::U8ToI64,
|
||||
Instruction::S16ToI64,
|
||||
Instruction::U16ToI64,
|
||||
Instruction::S32ToI64,
|
||||
Instruction::U32ToI64,
|
||||
Instruction::S64ToI64,
|
||||
Instruction::U64ToI64,
|
||||
Instruction::StringSize,
|
||||
];
|
||||
|
||||
assert_eq!(inputs.len(), outputs.len());
|
||||
|
@ -260,52 +260,47 @@ where
|
||||
(*function_index as u64).to_bytes(writer)?;
|
||||
}
|
||||
|
||||
Instruction::MemoryToString => 0x03_u8.to_bytes(writer)?,
|
||||
Instruction::S8FromI32 => 0x02_u8.to_bytes(writer)?,
|
||||
Instruction::S8FromI64 => 0x03_u8.to_bytes(writer)?,
|
||||
Instruction::S16FromI32 => 0x04_u8.to_bytes(writer)?,
|
||||
Instruction::S16FromI64 => 0x05_u8.to_bytes(writer)?,
|
||||
Instruction::S32FromI32 => 0x06_u8.to_bytes(writer)?,
|
||||
Instruction::S32FromI64 => 0x07_u8.to_bytes(writer)?,
|
||||
Instruction::S64FromI32 => 0x08_u8.to_bytes(writer)?,
|
||||
Instruction::S64FromI64 => 0x09_u8.to_bytes(writer)?,
|
||||
Instruction::I32FromS8 => 0x0a_u8.to_bytes(writer)?,
|
||||
Instruction::I32FromS16 => 0x0b_u8.to_bytes(writer)?,
|
||||
Instruction::I32FromS32 => 0x0c_u8.to_bytes(writer)?,
|
||||
Instruction::I32FromS64 => 0x0d_u8.to_bytes(writer)?,
|
||||
Instruction::I64FromS8 => 0x0e_u8.to_bytes(writer)?,
|
||||
Instruction::I64FromS16 => 0x0f_u8.to_bytes(writer)?,
|
||||
Instruction::I64FromS32 => 0x10_u8.to_bytes(writer)?,
|
||||
Instruction::I64FromS64 => 0x11_u8.to_bytes(writer)?,
|
||||
Instruction::U8FromI32 => 0x12_u8.to_bytes(writer)?,
|
||||
Instruction::U8FromI64 => 0x13_u8.to_bytes(writer)?,
|
||||
Instruction::U16FromI32 => 0x14_u8.to_bytes(writer)?,
|
||||
Instruction::U16FromI64 => 0x15_u8.to_bytes(writer)?,
|
||||
Instruction::U32FromI32 => 0x16_u8.to_bytes(writer)?,
|
||||
Instruction::U32FromI64 => 0x17_u8.to_bytes(writer)?,
|
||||
Instruction::U64FromI32 => 0x18_u8.to_bytes(writer)?,
|
||||
Instruction::U64FromI64 => 0x19_u8.to_bytes(writer)?,
|
||||
Instruction::I32FromU8 => 0x1a_u8.to_bytes(writer)?,
|
||||
Instruction::I32FromU16 => 0x1b_u8.to_bytes(writer)?,
|
||||
Instruction::I32FromU32 => 0x1c_u8.to_bytes(writer)?,
|
||||
Instruction::I32FromU64 => 0x1d_u8.to_bytes(writer)?,
|
||||
Instruction::I64FromU8 => 0x1e_u8.to_bytes(writer)?,
|
||||
Instruction::I64FromU16 => 0x1f_u8.to_bytes(writer)?,
|
||||
Instruction::I64FromU32 => 0x20_u8.to_bytes(writer)?,
|
||||
Instruction::I64FromU64 => 0x21_u8.to_bytes(writer)?,
|
||||
|
||||
Instruction::StringToMemory { allocator_index } => {
|
||||
0x04_u8.to_bytes(writer)?;
|
||||
Instruction::StringLiftMemory => 0x22_u8.to_bytes(writer)?,
|
||||
|
||||
Instruction::StringLowerMemory { allocator_index } => {
|
||||
0x23_u8.to_bytes(writer)?;
|
||||
(*allocator_index as u64).to_bytes(writer)?;
|
||||
}
|
||||
|
||||
Instruction::I32ToS8 => 0x07_u8.to_bytes(writer)?,
|
||||
Instruction::I32ToS8X => 0x08_u8.to_bytes(writer)?,
|
||||
Instruction::I32ToU8 => 0x09_u8.to_bytes(writer)?,
|
||||
Instruction::I32ToS16 => 0x0a_u8.to_bytes(writer)?,
|
||||
Instruction::I32ToS16X => 0x0b_u8.to_bytes(writer)?,
|
||||
Instruction::I32ToU16 => 0x0c_u8.to_bytes(writer)?,
|
||||
Instruction::I32ToS32 => 0x0d_u8.to_bytes(writer)?,
|
||||
Instruction::I32ToU32 => 0x0e_u8.to_bytes(writer)?,
|
||||
Instruction::I32ToS64 => 0x0f_u8.to_bytes(writer)?,
|
||||
Instruction::I32ToU64 => 0x10_u8.to_bytes(writer)?,
|
||||
Instruction::I64ToS8 => 0x11_u8.to_bytes(writer)?,
|
||||
Instruction::I64ToS8X => 0x12_u8.to_bytes(writer)?,
|
||||
Instruction::I64ToU8 => 0x13_u8.to_bytes(writer)?,
|
||||
Instruction::I64ToS16 => 0x14_u8.to_bytes(writer)?,
|
||||
Instruction::I64ToS16X => 0x15_u8.to_bytes(writer)?,
|
||||
Instruction::I64ToU16 => 0x16_u8.to_bytes(writer)?,
|
||||
Instruction::I64ToS32 => 0x17_u8.to_bytes(writer)?,
|
||||
Instruction::I64ToS32X => 0x18_u8.to_bytes(writer)?,
|
||||
Instruction::I64ToU32 => 0x19_u8.to_bytes(writer)?,
|
||||
Instruction::I64ToS64 => 0x1a_u8.to_bytes(writer)?,
|
||||
Instruction::I64ToU64 => 0x1b_u8.to_bytes(writer)?,
|
||||
Instruction::S8ToI32 => 0x1c_u8.to_bytes(writer)?,
|
||||
Instruction::U8ToI32 => 0x1d_u8.to_bytes(writer)?,
|
||||
Instruction::S16ToI32 => 0x1e_u8.to_bytes(writer)?,
|
||||
Instruction::U16ToI32 => 0x1f_u8.to_bytes(writer)?,
|
||||
Instruction::S32ToI32 => 0x20_u8.to_bytes(writer)?,
|
||||
Instruction::U32ToI32 => 0x21_u8.to_bytes(writer)?,
|
||||
Instruction::S64ToI32 => 0x22_u8.to_bytes(writer)?,
|
||||
Instruction::S64ToI32X => 0x23_u8.to_bytes(writer)?,
|
||||
Instruction::U64ToI32 => 0x24_u8.to_bytes(writer)?,
|
||||
Instruction::U64ToI32X => 0x25_u8.to_bytes(writer)?,
|
||||
Instruction::S8ToI64 => 0x26_u8.to_bytes(writer)?,
|
||||
Instruction::U8ToI64 => 0x27_u8.to_bytes(writer)?,
|
||||
Instruction::S16ToI64 => 0x28_u8.to_bytes(writer)?,
|
||||
Instruction::U16ToI64 => 0x29_u8.to_bytes(writer)?,
|
||||
Instruction::S32ToI64 => 0x2a_u8.to_bytes(writer)?,
|
||||
Instruction::U32ToI64 => 0x2b_u8.to_bytes(writer)?,
|
||||
Instruction::S64ToI64 => 0x2c_u8.to_bytes(writer)?,
|
||||
Instruction::U64ToI64 => 0x2d_u8.to_bytes(writer)?,
|
||||
Instruction::StringSize => 0x24_u8.to_bytes(writer)?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -550,93 +545,81 @@ mod tests {
|
||||
vec![
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::CallCore { function_index: 1 },
|
||||
Instruction::MemoryToString,
|
||||
Instruction::StringToMemory { allocator_index: 1 },
|
||||
Instruction::I32ToS8,
|
||||
Instruction::I32ToS8X,
|
||||
Instruction::I32ToU8,
|
||||
Instruction::I32ToS16,
|
||||
Instruction::I32ToS16X,
|
||||
Instruction::I32ToU16,
|
||||
Instruction::I32ToS32,
|
||||
Instruction::I32ToU32,
|
||||
Instruction::I32ToS64,
|
||||
Instruction::I32ToU64,
|
||||
Instruction::I64ToS8,
|
||||
Instruction::I64ToS8X,
|
||||
Instruction::I64ToU8,
|
||||
Instruction::I64ToS16,
|
||||
Instruction::I64ToS16X,
|
||||
Instruction::I64ToU16,
|
||||
Instruction::I64ToS32,
|
||||
Instruction::I64ToS32X,
|
||||
Instruction::I64ToU32,
|
||||
Instruction::I64ToS64,
|
||||
Instruction::I64ToU64,
|
||||
Instruction::S8ToI32,
|
||||
Instruction::U8ToI32,
|
||||
Instruction::S16ToI32,
|
||||
Instruction::U16ToI32,
|
||||
Instruction::S32ToI32,
|
||||
Instruction::U32ToI32,
|
||||
Instruction::S64ToI32,
|
||||
Instruction::S64ToI32X,
|
||||
Instruction::U64ToI32,
|
||||
Instruction::U64ToI32X,
|
||||
Instruction::S8ToI64,
|
||||
Instruction::U8ToI64,
|
||||
Instruction::S16ToI64,
|
||||
Instruction::U16ToI64,
|
||||
Instruction::S32ToI64,
|
||||
Instruction::U32ToI64,
|
||||
Instruction::S64ToI64,
|
||||
Instruction::U64ToI64,
|
||||
Instruction::S8FromI32,
|
||||
Instruction::S8FromI64,
|
||||
Instruction::S16FromI32,
|
||||
Instruction::S16FromI64,
|
||||
Instruction::S32FromI32,
|
||||
Instruction::S32FromI64,
|
||||
Instruction::S64FromI32,
|
||||
Instruction::S64FromI64,
|
||||
Instruction::I32FromS8,
|
||||
Instruction::I32FromS16,
|
||||
Instruction::I32FromS32,
|
||||
Instruction::I32FromS64,
|
||||
Instruction::I64FromS8,
|
||||
Instruction::I64FromS16,
|
||||
Instruction::I64FromS32,
|
||||
Instruction::I64FromS64,
|
||||
Instruction::U8FromI32,
|
||||
Instruction::U8FromI64,
|
||||
Instruction::U16FromI32,
|
||||
Instruction::U16FromI64,
|
||||
Instruction::U32FromI32,
|
||||
Instruction::U32FromI64,
|
||||
Instruction::U64FromI32,
|
||||
Instruction::U64FromI64,
|
||||
Instruction::I32FromU8,
|
||||
Instruction::I32FromU16,
|
||||
Instruction::I32FromU32,
|
||||
Instruction::I32FromU64,
|
||||
Instruction::I64FromU8,
|
||||
Instruction::I64FromU16,
|
||||
Instruction::I64FromU32,
|
||||
Instruction::I64FromU64,
|
||||
Instruction::StringLiftMemory,
|
||||
Instruction::StringLowerMemory { allocator_index: 1 },
|
||||
Instruction::StringSize,
|
||||
],
|
||||
&[
|
||||
0x2b, // list of 43 items
|
||||
0x25, // list of 37 items
|
||||
0x00, 0x01, // ArgumentGet { index: 1 }
|
||||
0x01, 0x01, // CallCore { function_index: 1 }
|
||||
0x03, // MemoryToString
|
||||
0x04, 0x01, // StringToMemory { allocator_index: 1 }
|
||||
0x07, // I32ToS8
|
||||
0x08, // I32ToS8X
|
||||
0x09, // I32ToU8
|
||||
0x0a, // I32ToS16
|
||||
0x0b, // I32ToS16X
|
||||
0x0c, // I32ToU16
|
||||
0x0d, // I32ToS32
|
||||
0x0e, // I32ToU32
|
||||
0x0f, // I32ToS64
|
||||
0x10, // I32ToU64
|
||||
0x11, // I64ToS8
|
||||
0x12, // I64ToS8X
|
||||
0x13, // I64ToU8
|
||||
0x14, // I64ToS16
|
||||
0x15, // I64ToS16X
|
||||
0x16, // I64ToU16
|
||||
0x17, // I64ToS32
|
||||
0x18, // I64ToS32X
|
||||
0x19, // I64ToU32
|
||||
0x1a, // I64ToS64
|
||||
0x1b, // I64ToU64
|
||||
0x1c, // S8ToI32
|
||||
0x1d, // U8ToI32
|
||||
0x1e, // S16ToI32
|
||||
0x1f, // U16ToI32
|
||||
0x20, // S32ToI32
|
||||
0x21, // U32ToI32
|
||||
0x22, // S64ToI32
|
||||
0x23, // S64ToI32X
|
||||
0x24, // U64ToI32
|
||||
0x25, // U64ToI32X
|
||||
0x26, // S8ToI64
|
||||
0x27, // U8ToI64
|
||||
0x28, // S16ToI64
|
||||
0x29, // U16ToI64
|
||||
0x2a, // S32ToI64
|
||||
0x2b, // U32ToI64
|
||||
0x2c, // S64ToI64
|
||||
0x2d, // U64ToI64
|
||||
0x02, // S8FromI32
|
||||
0x03, // S8FromI64
|
||||
0x04, // S16FromI32
|
||||
0x05, // S16FromI64
|
||||
0x06, // S32FromI32
|
||||
0x07, // S32FromI64
|
||||
0x08, // S64FromI32
|
||||
0x09, // S64FromI64
|
||||
0x0a, // I32FromS8
|
||||
0x0b, // I32FromS16
|
||||
0x0c, // I32FromS32
|
||||
0x0d, // I32FromS64
|
||||
0x0e, // I64FromS8
|
||||
0x0f, // I64FromS16
|
||||
0x10, // I64FromS32
|
||||
0x11, // I64FromS64
|
||||
0x12, // U8FromI32
|
||||
0x13, // U8FromI64
|
||||
0x14, // U16FromI32
|
||||
0x15, // U16FromI64
|
||||
0x16, // U32FromI32
|
||||
0x17, // U32FromI64
|
||||
0x18, // U64FromI32
|
||||
0x19, // U64FromI64
|
||||
0x1a, // I32FromU8
|
||||
0x1b, // I32FromU16
|
||||
0x1c, // I32FromU32
|
||||
0x1d, // I32FromU64
|
||||
0x1e, // I64FromU8
|
||||
0x1f, // I64FromU16
|
||||
0x20, // I64FromU32
|
||||
0x21, // I64FromU64
|
||||
0x22, // StringLiftMemory
|
||||
0x23, 0x01, // StringLowerMemory { allocator_index: 1 }
|
||||
0x24, // StringSize
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -85,49 +85,43 @@ impl ToString for &Instruction {
|
||||
match self {
|
||||
Instruction::ArgumentGet { index } => format!("arg.get {}", index),
|
||||
Instruction::CallCore { function_index } => format!("call-core {}", function_index),
|
||||
Instruction::MemoryToString => "memory-to-string".into(),
|
||||
Instruction::StringToMemory { allocator_index } => {
|
||||
format!(r#"string-to-memory {}"#, allocator_index)
|
||||
Instruction::S8FromI32 => "s8.from_i32".into(),
|
||||
Instruction::S8FromI64 => "s8.from_i64".into(),
|
||||
Instruction::S16FromI32 => "s16.from_i32".into(),
|
||||
Instruction::S16FromI64 => "s16.from_i64".into(),
|
||||
Instruction::S32FromI32 => "s32.from_i32".into(),
|
||||
Instruction::S32FromI64 => "s32.from_i64".into(),
|
||||
Instruction::S64FromI32 => "s64.from_i32".into(),
|
||||
Instruction::S64FromI64 => "s64.from_i64".into(),
|
||||
Instruction::I32FromS8 => "i32.from_s8".into(),
|
||||
Instruction::I32FromS16 => "i32.from_s16".into(),
|
||||
Instruction::I32FromS32 => "i32.from_s32".into(),
|
||||
Instruction::I32FromS64 => "i32.from_s64".into(),
|
||||
Instruction::I64FromS8 => "i64.from_s8".into(),
|
||||
Instruction::I64FromS16 => "i64.from_s16".into(),
|
||||
Instruction::I64FromS32 => "i64.from_s32".into(),
|
||||
Instruction::I64FromS64 => "i64.from_s64".into(),
|
||||
Instruction::U8FromI32 => "u8.from_i32".into(),
|
||||
Instruction::U8FromI64 => "u8.from_i64".into(),
|
||||
Instruction::U16FromI32 => "u16.from_i32".into(),
|
||||
Instruction::U16FromI64 => "u16.from_i64".into(),
|
||||
Instruction::U32FromI32 => "u32.from_i32".into(),
|
||||
Instruction::U32FromI64 => "u32.from_i64".into(),
|
||||
Instruction::U64FromI32 => "u64.from_i32".into(),
|
||||
Instruction::U64FromI64 => "u64.from_i64".into(),
|
||||
Instruction::I32FromU8 => "i32.from_u8".into(),
|
||||
Instruction::I32FromU16 => "i32.from_u16".into(),
|
||||
Instruction::I32FromU32 => "i32.from_u32".into(),
|
||||
Instruction::I32FromU64 => "i32.from_u64".into(),
|
||||
Instruction::I64FromU8 => "i64.from_u8".into(),
|
||||
Instruction::I64FromU16 => "i64.from_u16".into(),
|
||||
Instruction::I64FromU32 => "i64.from_u32".into(),
|
||||
Instruction::I64FromU64 => "i64.from_u64".into(),
|
||||
Instruction::StringLiftMemory => "string.lift_memory".into(),
|
||||
Instruction::StringLowerMemory { allocator_index } => {
|
||||
format!(r#"string.lower_memory {}"#, allocator_index)
|
||||
}
|
||||
Instruction::I32ToS8 => "i32-to-s8".into(),
|
||||
Instruction::I32ToS8X => "i32-to-s8x".into(),
|
||||
Instruction::I32ToU8 => "i32-to-u8".into(),
|
||||
Instruction::I32ToS16 => "i32-to-s16".into(),
|
||||
Instruction::I32ToS16X => "i32-to-s16x".into(),
|
||||
Instruction::I32ToU16 => "i32-to-u16".into(),
|
||||
Instruction::I32ToS32 => "i32-to-s32".into(),
|
||||
Instruction::I32ToU32 => "i32-to-u32".into(),
|
||||
Instruction::I32ToS64 => "i32-to-s64".into(),
|
||||
Instruction::I32ToU64 => "i32-to-u64".into(),
|
||||
Instruction::I64ToS8 => "i64-to-s8".into(),
|
||||
Instruction::I64ToS8X => "i64-to-s8x".into(),
|
||||
Instruction::I64ToU8 => "i64-to-u8".into(),
|
||||
Instruction::I64ToS16 => "i64-to-s16".into(),
|
||||
Instruction::I64ToS16X => "i64-to-s16x".into(),
|
||||
Instruction::I64ToU16 => "i64-to-u16".into(),
|
||||
Instruction::I64ToS32 => "i64-to-s32".into(),
|
||||
Instruction::I64ToS32X => "i64-to-s32x".into(),
|
||||
Instruction::I64ToU32 => "i64-to-u32".into(),
|
||||
Instruction::I64ToS64 => "i64-to-s64".into(),
|
||||
Instruction::I64ToU64 => "i64-to-u64".into(),
|
||||
Instruction::S8ToI32 => "s8-to-i32".into(),
|
||||
Instruction::U8ToI32 => "u8-to-i32".into(),
|
||||
Instruction::S16ToI32 => "s16-to-i32".into(),
|
||||
Instruction::U16ToI32 => "u16-to-i32".into(),
|
||||
Instruction::S32ToI32 => "s32-to-i32".into(),
|
||||
Instruction::U32ToI32 => "u32-to-i32".into(),
|
||||
Instruction::S64ToI32 => "s64-to-i32".into(),
|
||||
Instruction::S64ToI32X => "s64-to-i32x".into(),
|
||||
Instruction::U64ToI32 => "u64-to-i32".into(),
|
||||
Instruction::U64ToI32X => "u64-to-i32x".into(),
|
||||
Instruction::S8ToI64 => "s8-to-i64".into(),
|
||||
Instruction::U8ToI64 => "u8-to-i64".into(),
|
||||
Instruction::S16ToI64 => "s16-to-i64".into(),
|
||||
Instruction::U16ToI64 => "u16-to-i64".into(),
|
||||
Instruction::S32ToI64 => "s32-to-i64".into(),
|
||||
Instruction::U32ToI64 => "u32-to-i64".into(),
|
||||
Instruction::S64ToI64 => "s64-to-i64".into(),
|
||||
Instruction::U64ToI64 => "u64-to-i64".into(),
|
||||
Instruction::StringSize => "string.size".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -361,95 +355,83 @@ mod tests {
|
||||
let inputs: Vec<String> = vec![
|
||||
(&Instruction::ArgumentGet { index: 7 }).to_string(),
|
||||
(&Instruction::CallCore { function_index: 7 }).to_string(),
|
||||
(&Instruction::MemoryToString).to_string(),
|
||||
(&Instruction::StringToMemory {
|
||||
(&Instruction::S8FromI32).to_string(),
|
||||
(&Instruction::S8FromI64).to_string(),
|
||||
(&Instruction::S16FromI32).to_string(),
|
||||
(&Instruction::S16FromI64).to_string(),
|
||||
(&Instruction::S32FromI32).to_string(),
|
||||
(&Instruction::S32FromI64).to_string(),
|
||||
(&Instruction::S64FromI32).to_string(),
|
||||
(&Instruction::S64FromI64).to_string(),
|
||||
(&Instruction::I32FromS8).to_string(),
|
||||
(&Instruction::I32FromS16).to_string(),
|
||||
(&Instruction::I32FromS32).to_string(),
|
||||
(&Instruction::I32FromS64).to_string(),
|
||||
(&Instruction::I64FromS8).to_string(),
|
||||
(&Instruction::I64FromS16).to_string(),
|
||||
(&Instruction::I64FromS32).to_string(),
|
||||
(&Instruction::I64FromS64).to_string(),
|
||||
(&Instruction::U8FromI32).to_string(),
|
||||
(&Instruction::U8FromI64).to_string(),
|
||||
(&Instruction::U16FromI32).to_string(),
|
||||
(&Instruction::U16FromI64).to_string(),
|
||||
(&Instruction::U32FromI32).to_string(),
|
||||
(&Instruction::U32FromI64).to_string(),
|
||||
(&Instruction::U64FromI32).to_string(),
|
||||
(&Instruction::U64FromI64).to_string(),
|
||||
(&Instruction::I32FromU8).to_string(),
|
||||
(&Instruction::I32FromU16).to_string(),
|
||||
(&Instruction::I32FromU32).to_string(),
|
||||
(&Instruction::I32FromU64).to_string(),
|
||||
(&Instruction::I64FromU8).to_string(),
|
||||
(&Instruction::I64FromU16).to_string(),
|
||||
(&Instruction::I64FromU32).to_string(),
|
||||
(&Instruction::I64FromU64).to_string(),
|
||||
(&Instruction::StringLiftMemory).to_string(),
|
||||
(&Instruction::StringLowerMemory {
|
||||
allocator_index: 42,
|
||||
})
|
||||
.to_string(),
|
||||
(&Instruction::I32ToS8).to_string(),
|
||||
(&Instruction::I32ToS8X).to_string(),
|
||||
(&Instruction::I32ToU8).to_string(),
|
||||
(&Instruction::I32ToS16).to_string(),
|
||||
(&Instruction::I32ToS16X).to_string(),
|
||||
(&Instruction::I32ToU16).to_string(),
|
||||
(&Instruction::I32ToS32).to_string(),
|
||||
(&Instruction::I32ToU32).to_string(),
|
||||
(&Instruction::I32ToS64).to_string(),
|
||||
(&Instruction::I32ToU64).to_string(),
|
||||
(&Instruction::I64ToS8).to_string(),
|
||||
(&Instruction::I64ToS8X).to_string(),
|
||||
(&Instruction::I64ToU8).to_string(),
|
||||
(&Instruction::I64ToS16).to_string(),
|
||||
(&Instruction::I64ToS16X).to_string(),
|
||||
(&Instruction::I64ToU16).to_string(),
|
||||
(&Instruction::I64ToS32).to_string(),
|
||||
(&Instruction::I64ToS32X).to_string(),
|
||||
(&Instruction::I64ToU32).to_string(),
|
||||
(&Instruction::I64ToS64).to_string(),
|
||||
(&Instruction::I64ToU64).to_string(),
|
||||
(&Instruction::S8ToI32).to_string(),
|
||||
(&Instruction::U8ToI32).to_string(),
|
||||
(&Instruction::S16ToI32).to_string(),
|
||||
(&Instruction::U16ToI32).to_string(),
|
||||
(&Instruction::S32ToI32).to_string(),
|
||||
(&Instruction::U32ToI32).to_string(),
|
||||
(&Instruction::S64ToI32).to_string(),
|
||||
(&Instruction::S64ToI32X).to_string(),
|
||||
(&Instruction::U64ToI32).to_string(),
|
||||
(&Instruction::U64ToI32X).to_string(),
|
||||
(&Instruction::S8ToI64).to_string(),
|
||||
(&Instruction::U8ToI64).to_string(),
|
||||
(&Instruction::S16ToI64).to_string(),
|
||||
(&Instruction::U16ToI64).to_string(),
|
||||
(&Instruction::S32ToI64).to_string(),
|
||||
(&Instruction::U32ToI64).to_string(),
|
||||
(&Instruction::S64ToI64).to_string(),
|
||||
(&Instruction::U64ToI64).to_string(),
|
||||
(&Instruction::StringSize).to_string(),
|
||||
];
|
||||
let outputs = vec![
|
||||
"arg.get 7",
|
||||
"call-core 7",
|
||||
"memory-to-string",
|
||||
"string-to-memory 42",
|
||||
"i32-to-s8",
|
||||
"i32-to-s8x",
|
||||
"i32-to-u8",
|
||||
"i32-to-s16",
|
||||
"i32-to-s16x",
|
||||
"i32-to-u16",
|
||||
"i32-to-s32",
|
||||
"i32-to-u32",
|
||||
"i32-to-s64",
|
||||
"i32-to-u64",
|
||||
"i64-to-s8",
|
||||
"i64-to-s8x",
|
||||
"i64-to-u8",
|
||||
"i64-to-s16",
|
||||
"i64-to-s16x",
|
||||
"i64-to-u16",
|
||||
"i64-to-s32",
|
||||
"i64-to-s32x",
|
||||
"i64-to-u32",
|
||||
"i64-to-s64",
|
||||
"i64-to-u64",
|
||||
"s8-to-i32",
|
||||
"u8-to-i32",
|
||||
"s16-to-i32",
|
||||
"u16-to-i32",
|
||||
"s32-to-i32",
|
||||
"u32-to-i32",
|
||||
"s64-to-i32",
|
||||
"s64-to-i32x",
|
||||
"u64-to-i32",
|
||||
"u64-to-i32x",
|
||||
"s8-to-i64",
|
||||
"u8-to-i64",
|
||||
"s16-to-i64",
|
||||
"u16-to-i64",
|
||||
"s32-to-i64",
|
||||
"u32-to-i64",
|
||||
"s64-to-i64",
|
||||
"u64-to-i64",
|
||||
"s8.from_i32",
|
||||
"s8.from_i64",
|
||||
"s16.from_i32",
|
||||
"s16.from_i64",
|
||||
"s32.from_i32",
|
||||
"s32.from_i64",
|
||||
"s64.from_i32",
|
||||
"s64.from_i64",
|
||||
"i32.from_s8",
|
||||
"i32.from_s16",
|
||||
"i32.from_s32",
|
||||
"i32.from_s64",
|
||||
"i64.from_s8",
|
||||
"i64.from_s16",
|
||||
"i64.from_s32",
|
||||
"i64.from_s64",
|
||||
"u8.from_i32",
|
||||
"u8.from_i64",
|
||||
"u16.from_i32",
|
||||
"u16.from_i64",
|
||||
"u32.from_i32",
|
||||
"u32.from_i64",
|
||||
"u64.from_i32",
|
||||
"u64.from_i64",
|
||||
"i32.from_u8",
|
||||
"i32.from_u16",
|
||||
"i32.from_u32",
|
||||
"i32.from_u64",
|
||||
"i64.from_u8",
|
||||
"i64.from_u16",
|
||||
"i64.from_u32",
|
||||
"i64.from_u64",
|
||||
"string.lift_memory",
|
||||
"string.lower_memory 42",
|
||||
"string.size",
|
||||
];
|
||||
|
||||
assert_eq!(inputs, outputs);
|
||||
|
@ -15,129 +15,111 @@ pub enum Instruction {
|
||||
function_index: usize,
|
||||
},
|
||||
|
||||
/// The `memory-to-string` instruction.
|
||||
MemoryToString,
|
||||
/// The `s8.from_i32` instruction.
|
||||
S8FromI32,
|
||||
|
||||
/// The `string-to-memory` instruction.
|
||||
StringToMemory {
|
||||
/// The `s8.from_i64` instruction.
|
||||
S8FromI64,
|
||||
|
||||
/// The `s16.from_i32` instruction.
|
||||
S16FromI32,
|
||||
|
||||
/// The `s16.from_i64` instruction.
|
||||
S16FromI64,
|
||||
|
||||
/// The `s32.from_i32` instruction.
|
||||
S32FromI32,
|
||||
|
||||
/// The `s32.from_i64` instruction.
|
||||
S32FromI64,
|
||||
|
||||
/// The `s64.from_i32` instruction.
|
||||
S64FromI32,
|
||||
|
||||
/// The `s64.from_i64` instruction.
|
||||
S64FromI64,
|
||||
|
||||
/// The `i32.from_s8` instruction.
|
||||
I32FromS8,
|
||||
|
||||
/// The `i32.from_s16` instruction.
|
||||
I32FromS16,
|
||||
|
||||
/// The `i32.from_s32` instruction.
|
||||
I32FromS32,
|
||||
|
||||
/// The `i32.from_s64` instruction.
|
||||
I32FromS64,
|
||||
|
||||
/// The `i64.from_s8` instruction.
|
||||
I64FromS8,
|
||||
|
||||
/// The `i64.from_s16` instruction.
|
||||
I64FromS16,
|
||||
|
||||
/// The `i64.from_s32` instruction.
|
||||
I64FromS32,
|
||||
|
||||
/// The `i64.from_s64` instruction.
|
||||
I64FromS64,
|
||||
|
||||
/// The `u8.from_i32` instruction.
|
||||
U8FromI32,
|
||||
|
||||
/// The `u8.from_i64` instruction.
|
||||
U8FromI64,
|
||||
|
||||
/// The `u16.from_i32` instruction.
|
||||
U16FromI32,
|
||||
|
||||
/// The `u16.from_i64` instruction.
|
||||
U16FromI64,
|
||||
|
||||
/// The `u32.from_i32` instruction.
|
||||
U32FromI32,
|
||||
|
||||
/// The `u32.from_i64` instruction.
|
||||
U32FromI64,
|
||||
|
||||
/// The `u64.from_i32` instruction.
|
||||
U64FromI32,
|
||||
|
||||
/// The `u64.from_i64` instruction.
|
||||
U64FromI64,
|
||||
|
||||
/// The `i32.from_u8` instruction.
|
||||
I32FromU8,
|
||||
|
||||
/// The `i32.from_u16` instruction.
|
||||
I32FromU16,
|
||||
|
||||
/// The `i32.from_u32` instruction.
|
||||
I32FromU32,
|
||||
|
||||
/// The `i32.from_u64` instruction.
|
||||
I32FromU64,
|
||||
|
||||
/// The `i64.from_u8` instruction.
|
||||
I64FromU8,
|
||||
|
||||
/// The `i64.from_u16` instruction.
|
||||
I64FromU16,
|
||||
|
||||
/// The `i64.from_u32` instruction.
|
||||
I64FromU32,
|
||||
|
||||
/// The `i64.from_u64` instruction.
|
||||
I64FromU64,
|
||||
|
||||
/// The `string.lift_memory` instruction.
|
||||
StringLiftMemory,
|
||||
|
||||
/// The `string.lower_memory` instruction.
|
||||
StringLowerMemory {
|
||||
/// The allocator function index.
|
||||
allocator_index: u32,
|
||||
},
|
||||
|
||||
/// The `i32-to-s8,` instruction.
|
||||
I32ToS8,
|
||||
|
||||
/// The `i32-to-s8x,` instruction.
|
||||
I32ToS8X,
|
||||
|
||||
/// The `i32-to-u8,` instruction.
|
||||
I32ToU8,
|
||||
|
||||
/// The `i32-to-s16,` instruction.
|
||||
I32ToS16,
|
||||
|
||||
/// The `i32-to-s16x,` instruction.
|
||||
I32ToS16X,
|
||||
|
||||
/// The `i32-to-u16,` instruction.
|
||||
I32ToU16,
|
||||
|
||||
/// The `i32-to-s32,` instruction.
|
||||
I32ToS32,
|
||||
|
||||
/// The `i32-to-u32,` instruction.
|
||||
I32ToU32,
|
||||
|
||||
/// The `i32-to-s64,` instruction.
|
||||
I32ToS64,
|
||||
|
||||
/// The `i32-to-u64,` instruction.
|
||||
I32ToU64,
|
||||
|
||||
/// The `i64-to-s8,` instruction.
|
||||
I64ToS8,
|
||||
|
||||
/// The `i64-to-s8x,` instruction.
|
||||
I64ToS8X,
|
||||
|
||||
/// The `i64-to-u8,` instruction.
|
||||
I64ToU8,
|
||||
|
||||
/// The `i64-to-s16,` instruction.
|
||||
I64ToS16,
|
||||
|
||||
/// The `i64-to-s16x,` instruction.
|
||||
I64ToS16X,
|
||||
|
||||
/// The `i64-to-u16,` instruction.
|
||||
I64ToU16,
|
||||
|
||||
/// The `i64-to-s32,` instruction.
|
||||
I64ToS32,
|
||||
|
||||
/// The `i64-to-s32x,` instruction.
|
||||
I64ToS32X,
|
||||
|
||||
/// The `i64-to-u32,` instruction.
|
||||
I64ToU32,
|
||||
|
||||
/// The `i64-to-s64,` instruction.
|
||||
I64ToS64,
|
||||
|
||||
/// The `i64-to-u64,` instruction.
|
||||
I64ToU64,
|
||||
|
||||
/// The `s8-to-i32,` instruction.
|
||||
S8ToI32,
|
||||
|
||||
/// The `u8-to-i32,` instruction.
|
||||
U8ToI32,
|
||||
|
||||
/// The `s16-to-i32,` instruction.
|
||||
S16ToI32,
|
||||
|
||||
/// The `u16-to-i32,` instruction.
|
||||
U16ToI32,
|
||||
|
||||
/// The `s32-to-i32,` instruction.
|
||||
S32ToI32,
|
||||
|
||||
/// The `u32-to-i32,` instruction.
|
||||
U32ToI32,
|
||||
|
||||
/// The `s64-to-i32,` instruction.
|
||||
S64ToI32,
|
||||
|
||||
/// The `s64-to-i32x,` instruction.
|
||||
S64ToI32X,
|
||||
|
||||
/// The `u64-to-i32,` instruction.
|
||||
U64ToI32,
|
||||
|
||||
/// The `u64-to-i32x,` instruction.
|
||||
U64ToI32X,
|
||||
|
||||
/// The `s8-to-i64,` instruction.
|
||||
S8ToI64,
|
||||
|
||||
/// The `u8-to-i64,` instruction.
|
||||
U8ToI64,
|
||||
|
||||
/// The `s16-to-i64,` instruction.
|
||||
S16ToI64,
|
||||
|
||||
/// The `u16-to-i64,` instruction.
|
||||
U16ToI64,
|
||||
|
||||
/// The `s32-to-i64,` instruction.
|
||||
S32ToI64,
|
||||
|
||||
/// The `u32-to-i64,` instruction.
|
||||
U32ToI64,
|
||||
|
||||
/// The `s64-to-i64,` instruction.
|
||||
S64ToI64,
|
||||
|
||||
/// The `u64-to-i64,` instruction.
|
||||
U64ToI64,
|
||||
/// The `string.size` instruction.
|
||||
StringSize,
|
||||
}
|
||||
|
@ -70,8 +70,8 @@ mod tests {
|
||||
test_executable_instruction!(
|
||||
test_call_core =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::CallCore { function_index: 42 },
|
||||
],
|
||||
invocation_inputs: [
|
||||
@ -113,8 +113,8 @@ mod tests {
|
||||
test_executable_instruction!(
|
||||
test_call_core__invalid_types_in_the_stack =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::CallCore { function_index: 42 },
|
||||
],
|
||||
invocation_inputs: [
|
||||
@ -129,8 +129,8 @@ mod tests {
|
||||
test_executable_instruction!(
|
||||
test_call_core__failure_when_calling =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::CallCore { function_index: 42 },
|
||||
],
|
||||
invocation_inputs: [
|
||||
@ -160,8 +160,8 @@ mod tests {
|
||||
test_executable_instruction!(
|
||||
test_call_core__void =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::CallCore { function_index: 42 },
|
||||
],
|
||||
invocation_inputs: [
|
||||
|
@ -1,159 +0,0 @@
|
||||
use super::to_native;
|
||||
use crate::{
|
||||
errors::{InstructionError, InstructionErrorKind},
|
||||
interpreter::{wasm::values::InterfaceValue, Instruction},
|
||||
};
|
||||
use std::cell::Cell;
|
||||
|
||||
executable_instruction!(
|
||||
memory_to_string(instruction: Instruction) -> _ {
|
||||
move |runtime| -> _ {
|
||||
let inputs = runtime.stack.pop(2).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 2 },
|
||||
)
|
||||
})?;
|
||||
|
||||
let memory_index: u32 = 0;
|
||||
|
||||
let memory = runtime
|
||||
.wasm_instance
|
||||
.memory(memory_index as usize)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::MemoryIsMissing { memory_index },
|
||||
)
|
||||
})?;
|
||||
|
||||
let length = to_native::<i32>(&inputs[0], instruction)? as usize;
|
||||
let pointer = to_native::<i32>(&inputs[1], instruction)? as usize;
|
||||
let memory_view = memory.view();
|
||||
|
||||
if length == 0 {
|
||||
runtime.stack.push(InterfaceValue::String("".into()));
|
||||
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
if memory_view.len() <= pointer + length - 1 {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::MemoryOutOfBoundsAccess {
|
||||
index: pointer + length,
|
||||
length: memory_view.len(),
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
let data: Vec<u8> = (&memory_view[pointer..=pointer + length - 1])
|
||||
.iter()
|
||||
.map(Cell::get)
|
||||
.collect();
|
||||
|
||||
let string = String::from_utf8(data)
|
||||
.map_err(|error| InstructionError::new(instruction, InstructionErrorKind::String(error)))?;
|
||||
|
||||
runtime.stack.push(InterfaceValue::String(string));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
test_executable_instruction!(
|
||||
test_memory_to_string =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::MemoryToString,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(13),
|
||||
// ^^^^^^^ length
|
||||
InterfaceValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new("Hello, World!".as_bytes().iter().map(|u| Cell::new(*u)).collect()),
|
||||
..Default::default()
|
||||
},
|
||||
stack: [InterfaceValue::String("Hello, World!".into())],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_memory_to_string__empty_string =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::MemoryToString,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
InterfaceValue::I32(0),
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new(vec![]),
|
||||
..Default::default()
|
||||
},
|
||||
stack: [InterfaceValue::String("".into())],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_memory_to_string__read_out_of_memory =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::MemoryToString,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(13),
|
||||
// ^^^^^^^ length is too long
|
||||
InterfaceValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new("Hello!".as_bytes().iter().map(|u| Cell::new(*u)).collect()),
|
||||
..Default::default()
|
||||
},
|
||||
error: r#"`memory-to-string` read out of the memory bounds (index 13 > memory length 6)"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_memory_to_string__invalid_encoding =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::MemoryToString,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(4),
|
||||
// ^^^^^^ length is too long
|
||||
InterfaceValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new(vec![0, 159, 146, 150].iter().map(|b| Cell::new(*b)).collect::<Vec<Cell<u8>>>()),
|
||||
..Default::default()
|
||||
},
|
||||
error: r#"`memory-to-string` invalid utf-8 sequence of 1 bytes from index 1"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_memory_to_string__stack_is_too_small =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::MemoryToString,
|
||||
// ^^^^^^^^^^^^^^ `memory-to-string` expects 2 values on the stack, only one is present.
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(13),
|
||||
InterfaceValue::I32(0),
|
||||
],
|
||||
instance: Instance::new(),
|
||||
error: r#"`memory-to-string` needed to read `2` value(s) from the stack, but it doesn't contain enough data"#,
|
||||
);
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
mod argument_get;
|
||||
mod call_core;
|
||||
mod lowering_lifting;
|
||||
mod memory_to_string;
|
||||
mod string_to_memory;
|
||||
mod numbers;
|
||||
mod strings;
|
||||
|
||||
use crate::{
|
||||
errors::{InstructionError, InstructionErrorKind, InstructionResult, WasmValueNativeCastError},
|
||||
@ -13,10 +12,9 @@ use crate::{
|
||||
};
|
||||
pub(crate) use argument_get::argument_get;
|
||||
pub(crate) use call_core::call_core;
|
||||
pub(crate) use lowering_lifting::*;
|
||||
pub(crate) use memory_to_string::memory_to_string;
|
||||
pub(crate) use numbers::*;
|
||||
use std::convert::TryFrom;
|
||||
pub(crate) use string_to_memory::string_to_memory;
|
||||
pub(crate) use strings::*;
|
||||
|
||||
/// Just a short helper to map the error of a cast from an
|
||||
/// `InterfaceValue` to a native value.
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
use std::convert::TryInto;
|
||||
|
||||
macro_rules! lowering_lifting {
|
||||
($instruction_function_name:ident, $instruction_name:expr, $from_variant:ident, $to_variant:ident) => {
|
||||
($instruction_function_name:ident, $instruction_name:expr, $to_variant:ident, $from_variant:ident) => {
|
||||
executable_instruction!(
|
||||
$instruction_function_name(instruction: Instruction) -> _ {
|
||||
move |runtime| -> _ {
|
||||
@ -52,316 +52,316 @@ macro_rules! lowering_lifting {
|
||||
};
|
||||
}
|
||||
|
||||
lowering_lifting!(i32_to_s8, "i32-to-s8", I32, S8);
|
||||
lowering_lifting!(i32_to_u8, "i32-to-u8", I32, U8);
|
||||
lowering_lifting!(i32_to_s16, "i32-to-s16", I32, S16);
|
||||
lowering_lifting!(i32_to_u16, "i32-to-u16", I32, U16);
|
||||
lowering_lifting!(i32_to_s32, "i32-to-s32", I32, S32);
|
||||
lowering_lifting!(i32_to_u32, "i32-to-u32", I32, U32);
|
||||
lowering_lifting!(i32_to_s64, "i32-to-s64", I32, S64);
|
||||
lowering_lifting!(i32_to_u64, "i32-to-u64", I32, U64);
|
||||
lowering_lifting!(i64_to_s8, "i64-to-s8", I64, S8);
|
||||
lowering_lifting!(i64_to_u8, "i64-to-u8", I64, U8);
|
||||
lowering_lifting!(i64_to_s16, "i64-to-s16", I64, S16);
|
||||
lowering_lifting!(i64_to_u16, "i64-to-u16", I64, U16);
|
||||
lowering_lifting!(i64_to_s32, "i64-to-s32", I64, S32);
|
||||
lowering_lifting!(i64_to_u32, "i64-to-u32", I64, U32);
|
||||
lowering_lifting!(i64_to_s64, "i64-to-s64", I64, S64);
|
||||
lowering_lifting!(i64_to_u64, "i64-to-u64", I64, U64);
|
||||
lowering_lifting!(s8_to_i32, "s8-to-i32", S8, I32);
|
||||
lowering_lifting!(u8_to_i32, "u8-to-i32", U8, I32);
|
||||
lowering_lifting!(s16_to_i32, "s16-to-i32", S16, I32);
|
||||
lowering_lifting!(u16_to_i32, "u16-to-i32", U16, I32);
|
||||
lowering_lifting!(s32_to_i32, "s32-to-i32", S32, I32);
|
||||
lowering_lifting!(u32_to_i32, "u32-to-i32", U32, I32);
|
||||
lowering_lifting!(s64_to_i32, "s64-to-i32", S64, I32);
|
||||
lowering_lifting!(u64_to_i32, "u64-to-i32", U64, I32);
|
||||
lowering_lifting!(s8_to_i64, "s8-to-i64", S8, I64);
|
||||
lowering_lifting!(u8_to_i64, "u8-to-i64", U8, I64);
|
||||
lowering_lifting!(s16_to_i64, "s16-to-i64", S16, I64);
|
||||
lowering_lifting!(u16_to_i64, "u16-to-i64", U16, I64);
|
||||
lowering_lifting!(s32_to_i64, "s32-to-i64", S32, I64);
|
||||
lowering_lifting!(u32_to_i64, "u32-to-i64", U32, I64);
|
||||
lowering_lifting!(s64_to_i64, "s64-to-i64", S64, I64);
|
||||
lowering_lifting!(u64_to_i64, "u64-to-i64", U64, I64);
|
||||
lowering_lifting!(s8_from_i32, "s8.from_i32", S8, I32);
|
||||
lowering_lifting!(s8_from_i64, "s8.from_i64", S8, I64);
|
||||
lowering_lifting!(s16_from_i32, "s16.from_i32", S16, I32);
|
||||
lowering_lifting!(s16_from_i64, "s16.from_i64", S16, I64);
|
||||
lowering_lifting!(s32_from_i32, "s32.from_i32", S32, I32);
|
||||
lowering_lifting!(s32_from_i64, "s32.from_i64", S32, I64);
|
||||
lowering_lifting!(s64_from_i32, "s64.from_i32", S64, I32);
|
||||
lowering_lifting!(s64_from_i64, "s64.from_i64", S64, I64);
|
||||
lowering_lifting!(i32_from_s8, "i32.from_s8", I32, S8);
|
||||
lowering_lifting!(i32_from_s16, "i32.from_s16", I32, S16);
|
||||
lowering_lifting!(i32_from_s32, "i32.from_s32", I32, S32);
|
||||
lowering_lifting!(i32_from_s64, "i32.from_s64", I32, S64);
|
||||
lowering_lifting!(i64_from_s8, "i64.from_s8", I64, S8);
|
||||
lowering_lifting!(i64_from_s16, "i64.from_s16", I64, S16);
|
||||
lowering_lifting!(i64_from_s32, "i64.from_s32", I64, S32);
|
||||
lowering_lifting!(i64_from_s64, "i64.from_s64", I64, S64);
|
||||
lowering_lifting!(u8_from_i32, "u8.from_i32", U8, I32);
|
||||
lowering_lifting!(u8_from_i64, "u8.from_i64", U8, I64);
|
||||
lowering_lifting!(u16_from_i32, "u16.from_i32", U16, I32);
|
||||
lowering_lifting!(u16_from_i64, "u16.from_i64", U16, I64);
|
||||
lowering_lifting!(u32_from_i32, "u32.from_i32", U32, I32);
|
||||
lowering_lifting!(u32_from_i64, "u32.from_i64", U32, I64);
|
||||
lowering_lifting!(u64_from_i32, "u64.from_i32", U64, I32);
|
||||
lowering_lifting!(u64_from_i64, "u64.from_i64", U64, I64);
|
||||
lowering_lifting!(i32_from_u8, "i32.from_u8", I32, U8);
|
||||
lowering_lifting!(i32_from_u16, "i32.from_u16", I32, U16);
|
||||
lowering_lifting!(i32_from_u32, "i32.from_u32", I32, U32);
|
||||
lowering_lifting!(i32_from_u64, "i32.from_u64", I32, U64);
|
||||
lowering_lifting!(i64_from_u8, "i64.from_u8", I64, U8);
|
||||
lowering_lifting!(i64_from_u16, "i64.from_u16", I64, U16);
|
||||
lowering_lifting!(i64_from_u32, "i64.from_u32", I64, U32);
|
||||
lowering_lifting!(i64_from_u64, "i64.from_u64", I64, U64);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
test_executable_instruction!(
|
||||
test_i32_to_s8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32ToS8],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S8(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_convert_fails =
|
||||
instructions: [Instruction::ArgumentGet { index: 0}, Instruction::I32ToS8],
|
||||
instructions: [Instruction::ArgumentGet { index: 0}, Instruction::S8FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(128)],
|
||||
instance: Instance::new(),
|
||||
error: "`i32-to-s8` failed to cast `I32` to `S8`"
|
||||
error: "`s8.from_i32` failed to cast `I32` to `S8`"
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_type_mismatch =
|
||||
instructions: [Instruction::ArgumentGet { index: 0}, Instruction::I32ToS8],
|
||||
instructions: [Instruction::ArgumentGet { index: 0}, Instruction::S8FromI32],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
error: "`i32-to-s8` read a value of type `I64` from the stack, but the type `I32` was expected"
|
||||
error: "`s8.from_i32` read a value of type `I64` from the stack, but the type `I32` was expected"
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_no_value_on_the_stack =
|
||||
instructions: [Instruction::I32ToS8],
|
||||
instructions: [Instruction::S8FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
error: "`i32-to-s8` needed to read `1` value(s) from the stack, but it doesn't contain enough data"
|
||||
error: "`s8.from_i32` needed to read `1` value(s) from the stack, but it doesn't contain enough data"
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_to_u8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32ToU8],
|
||||
test_s8_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S8FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U8(42)],
|
||||
stack: [InterfaceValue::S8(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_to_s16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32ToS16],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S16(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_to_u16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32ToU16],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U16(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_to_s32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32ToS32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_to_u32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32ToU32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_to_s64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32ToS64],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_to_u64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32ToU64],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_to_s8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64ToS8],
|
||||
test_s8_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S8FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S8(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_to_u8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64ToU8],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
test_s16_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S16FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U8(42)],
|
||||
stack: [InterfaceValue::S16(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_to_s16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64ToS16],
|
||||
test_s16_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S16FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S16(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_to_u16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64ToU16],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
test_s32_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S32FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U16(42)],
|
||||
stack: [InterfaceValue::S32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_to_s32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64ToS32],
|
||||
test_s32_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S32FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_to_u32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64ToU32],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
test_s64_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S64FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U32(42)],
|
||||
stack: [InterfaceValue::S64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_to_s64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64ToS64],
|
||||
test_s64_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S64FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_to_u64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64ToU64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s8_to_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S8ToI32],
|
||||
test_i32_from_s8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS8],
|
||||
invocation_inputs: [InterfaceValue::S8(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u8_to_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U8ToI32],
|
||||
invocation_inputs: [InterfaceValue::U8(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s16_to_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S16ToI32],
|
||||
test_i32_from_s16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS16],
|
||||
invocation_inputs: [InterfaceValue::S16(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u16_to_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U16ToI32],
|
||||
invocation_inputs: [InterfaceValue::U16(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s32_to_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S32ToI32],
|
||||
test_i32_from_s32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS32],
|
||||
invocation_inputs: [InterfaceValue::S32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u32_to_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U32ToI32],
|
||||
invocation_inputs: [InterfaceValue::U32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s64_to_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S64ToI32],
|
||||
test_i32_from_s64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS64],
|
||||
invocation_inputs: [InterfaceValue::S64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u64_to_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U64ToI32],
|
||||
test_i64_from_s8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS8],
|
||||
invocation_inputs: [InterfaceValue::S8(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_from_s16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS16],
|
||||
invocation_inputs: [InterfaceValue::S16(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_from_s32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS32],
|
||||
invocation_inputs: [InterfaceValue::S32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_from_s64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS64],
|
||||
invocation_inputs: [InterfaceValue::S64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u8_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U8FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U8(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u8_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U8FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U8(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u16_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U16FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U16(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u16_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U16FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U16(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u32_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U32FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u32_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U32FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u64_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U64FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u64_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U64FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_u8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU8],
|
||||
invocation_inputs: [InterfaceValue::U8(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_u16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU16],
|
||||
invocation_inputs: [InterfaceValue::U16(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_u32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU32],
|
||||
invocation_inputs: [InterfaceValue::U32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_u64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU64],
|
||||
invocation_inputs: [InterfaceValue::U64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s8_to_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S8ToI64],
|
||||
invocation_inputs: [InterfaceValue::S8(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u8_to_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U8ToI64],
|
||||
test_i64_from_u8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU8],
|
||||
invocation_inputs: [InterfaceValue::U8(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s16_to_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S16ToI64],
|
||||
invocation_inputs: [InterfaceValue::S16(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u16_to_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U16ToI64],
|
||||
test_i64_from_u16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU16],
|
||||
invocation_inputs: [InterfaceValue::U16(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s32_to_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S32ToI64],
|
||||
invocation_inputs: [InterfaceValue::S32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u32_to_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U32ToI64],
|
||||
test_i64_from_u32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU32],
|
||||
invocation_inputs: [InterfaceValue::U32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s64_to_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S64ToI64],
|
||||
invocation_inputs: [InterfaceValue::S64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u64_to_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U64ToI64],
|
||||
test_i64_from_u64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU64],
|
||||
invocation_inputs: [InterfaceValue::U64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
@ -1,175 +0,0 @@
|
||||
use super::to_native;
|
||||
use crate::{
|
||||
ast::InterfaceType,
|
||||
errors::{InstructionError, InstructionErrorKind},
|
||||
interpreter::{
|
||||
wasm::{
|
||||
structures::{FunctionIndex, TypedIndex},
|
||||
values::InterfaceValue,
|
||||
},
|
||||
Instruction,
|
||||
},
|
||||
};
|
||||
|
||||
executable_instruction!(
|
||||
string_to_memory(allocator_index: u32, instruction: Instruction) -> _ {
|
||||
move |runtime| -> _ {
|
||||
let instance = &mut runtime.wasm_instance;
|
||||
let index = FunctionIndex::new(allocator_index as usize);
|
||||
|
||||
let allocator = instance.local_or_import(index).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::LocalOrImportIsMissing { function_index: allocator_index },
|
||||
)
|
||||
})?;
|
||||
|
||||
if allocator.inputs() != [InterfaceType::I32] || allocator.outputs() != [InterfaceType::I32] {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::LocalOrImportSignatureMismatch {
|
||||
function_index: allocator_index,
|
||||
expected: (vec![InterfaceType::I32], vec![InterfaceType::I32]),
|
||||
received: (allocator.inputs().to_vec(), allocator.outputs().to_vec())
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
let string = runtime.stack.pop1().ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 }
|
||||
)
|
||||
})?;
|
||||
|
||||
let string: String = to_native(&string, instruction)?;
|
||||
let string_bytes = string.as_bytes();
|
||||
let string_length = string_bytes.len() as i32;
|
||||
|
||||
let outputs = allocator.call(&[InterfaceValue::I32(string_length)]).map_err(|_| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::LocalOrImportCall { function_index: allocator_index },
|
||||
)
|
||||
})?;
|
||||
let string_pointer: i32 = to_native(&outputs[0], instruction)?;
|
||||
|
||||
let memory_index: u32 = 0;
|
||||
let memory_view = instance
|
||||
.memory(memory_index as usize)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::MemoryIsMissing { memory_index }
|
||||
)
|
||||
})?
|
||||
.view();
|
||||
|
||||
for (nth, byte) in string_bytes.iter().enumerate() {
|
||||
memory_view[string_pointer as usize + nth].set(*byte);
|
||||
}
|
||||
|
||||
runtime.stack.push(InterfaceValue::I32(string_pointer));
|
||||
runtime.stack.push(InterfaceValue::I32(string_length));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
test_executable_instruction!(
|
||||
test_string_to_memory =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringToMemory { allocator_index: 43 },
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
instance: Instance::new(),
|
||||
stack: [
|
||||
InterfaceValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
InterfaceValue::I32(13),
|
||||
// ^^^^^^^ length
|
||||
]
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_to_memory__roundtrip_with_memory_to_string =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringToMemory { allocator_index: 43 },
|
||||
Instruction::MemoryToString,
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::String("Hello, World!".into())],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_to_memory__allocator_does_not_exist =
|
||||
instructions: [Instruction::StringToMemory { allocator_index: 43 }],
|
||||
invocation_inputs: [],
|
||||
instance: Instance { ..Default::default() },
|
||||
error: r#"`string-to-memory 43` the local or import function `43` doesn't exist"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_to_memory__stack_is_too_small =
|
||||
instructions: [
|
||||
Instruction::StringToMemory { allocator_index: 43 }
|
||||
// ^^ `43` expects 1 value on the stack, none is present
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
instance: Instance::new(),
|
||||
error: r#"`string-to-memory 43` needed to read `1` value(s) from the stack, but it doesn't contain enough data"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_to_memory__failure_when_calling_the_allocator =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringToMemory { allocator_index: 153 }
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
instance: {
|
||||
let mut instance = Instance::new();
|
||||
instance.locals_or_imports.insert(
|
||||
153,
|
||||
LocalImport {
|
||||
inputs: vec![InterfaceType::I32],
|
||||
outputs: vec![InterfaceType::I32],
|
||||
function: |_| Err(()),
|
||||
// ^^^^^^^ function fails
|
||||
},
|
||||
);
|
||||
|
||||
instance
|
||||
},
|
||||
error: r#"`string-to-memory 153` failed while calling the local or import function `153`"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_to_memory__invalid_allocator_signature =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringToMemory { allocator_index: 153 }
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
instance: {
|
||||
let mut instance = Instance::new();
|
||||
instance.locals_or_imports.insert(
|
||||
153,
|
||||
LocalImport {
|
||||
inputs: vec![InterfaceType::I32, InterfaceType::I32],
|
||||
outputs: vec![],
|
||||
function: |_| Err(()),
|
||||
},
|
||||
);
|
||||
|
||||
instance
|
||||
},
|
||||
error: r#"`string-to-memory 153` the local or import function `153` has the signature `[I32] -> [I32]` but it received values of kind `[I32, I32] -> []`"#,
|
||||
);
|
||||
}
|
386
lib/interface-types/src/interpreter/instructions/strings.rs
Normal file
386
lib/interface-types/src/interpreter/instructions/strings.rs
Normal file
@ -0,0 +1,386 @@
|
||||
use super::to_native;
|
||||
use crate::{
|
||||
ast::InterfaceType,
|
||||
errors::{InstructionError, InstructionErrorKind},
|
||||
interpreter::{
|
||||
wasm::{
|
||||
structures::{FunctionIndex, TypedIndex},
|
||||
values::InterfaceValue,
|
||||
},
|
||||
Instruction,
|
||||
},
|
||||
};
|
||||
use std::cell::Cell;
|
||||
|
||||
executable_instruction!(
|
||||
string_lift_memory(instruction: Instruction) -> _ {
|
||||
move |runtime| -> _ {
|
||||
let inputs = runtime.stack.pop(2).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 2 },
|
||||
)
|
||||
})?;
|
||||
|
||||
let memory_index: u32 = 0;
|
||||
|
||||
let memory = runtime
|
||||
.wasm_instance
|
||||
.memory(memory_index as usize)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::MemoryIsMissing { memory_index },
|
||||
)
|
||||
})?;
|
||||
|
||||
let pointer = to_native::<i32>(&inputs[0], instruction)? as usize;
|
||||
let length = to_native::<i32>(&inputs[1], instruction)? as usize;
|
||||
let memory_view = memory.view();
|
||||
|
||||
if length == 0 {
|
||||
runtime.stack.push(InterfaceValue::String("".into()));
|
||||
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
if memory_view.len() <= pointer + length - 1 {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::MemoryOutOfBoundsAccess {
|
||||
index: pointer + length,
|
||||
length: memory_view.len(),
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
let data: Vec<u8> = (&memory_view[pointer..=pointer + length - 1])
|
||||
.iter()
|
||||
.map(Cell::get)
|
||||
.collect();
|
||||
|
||||
let string = String::from_utf8(data)
|
||||
.map_err(|error| InstructionError::new(instruction, InstructionErrorKind::String(error)))?;
|
||||
|
||||
runtime.stack.push(InterfaceValue::String(string));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
executable_instruction!(
|
||||
string_lower_memory(allocator_index: u32, instruction: Instruction) -> _ {
|
||||
move |runtime| -> _ {
|
||||
let instance = &mut runtime.wasm_instance;
|
||||
let index = FunctionIndex::new(allocator_index as usize);
|
||||
|
||||
let allocator = instance.local_or_import(index).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::LocalOrImportIsMissing { function_index: allocator_index },
|
||||
)
|
||||
})?;
|
||||
|
||||
if allocator.inputs() != [InterfaceType::I32] || allocator.outputs() != [InterfaceType::I32] {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::LocalOrImportSignatureMismatch {
|
||||
function_index: allocator_index,
|
||||
expected: (vec![InterfaceType::I32], vec![InterfaceType::I32]),
|
||||
received: (allocator.inputs().to_vec(), allocator.outputs().to_vec())
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
let string = runtime.stack.pop1().ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 }
|
||||
)
|
||||
})?;
|
||||
|
||||
let string: String = to_native(&string, instruction)?;
|
||||
let string_bytes = string.as_bytes();
|
||||
let string_length = string_bytes.len() as i32;
|
||||
|
||||
let outputs = allocator.call(&[InterfaceValue::I32(string_length)]).map_err(|_| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::LocalOrImportCall { function_index: allocator_index },
|
||||
)
|
||||
})?;
|
||||
let string_pointer: i32 = to_native(&outputs[0], instruction)?;
|
||||
|
||||
let memory_index: u32 = 0;
|
||||
let memory_view = instance
|
||||
.memory(memory_index as usize)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::MemoryIsMissing { memory_index }
|
||||
)
|
||||
})?
|
||||
.view();
|
||||
|
||||
for (nth, byte) in string_bytes.iter().enumerate() {
|
||||
memory_view[string_pointer as usize + nth].set(*byte);
|
||||
}
|
||||
|
||||
runtime.stack.push(InterfaceValue::I32(string_pointer));
|
||||
runtime.stack.push(InterfaceValue::I32(string_length));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
executable_instruction!(
|
||||
string_size(instruction: Instruction) -> _ {
|
||||
move |runtime| -> _ {
|
||||
let value = runtime.stack.peek1().ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
)
|
||||
})?;
|
||||
|
||||
if let InterfaceValue::String(string) = value {
|
||||
let length = string.len() as i32;
|
||||
runtime.stack.push(InterfaceValue::I32(length));
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err(InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::String,
|
||||
received_type: value.into(),
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
test_executable_instruction!(
|
||||
test_string_lift_memory =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
InterfaceValue::I32(13),
|
||||
// ^^^^^^^ length
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new("Hello, World!".as_bytes().iter().map(|u| Cell::new(*u)).collect()),
|
||||
..Default::default()
|
||||
},
|
||||
stack: [InterfaceValue::String("Hello, World!".into())],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_lift_memory__empty_string =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
InterfaceValue::I32(0),
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new(vec![]),
|
||||
..Default::default()
|
||||
},
|
||||
stack: [InterfaceValue::String("".into())],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_lift_memory__read_out_of_memory =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
InterfaceValue::I32(13),
|
||||
// ^^^^^^^ length is too long
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new("Hello!".as_bytes().iter().map(|u| Cell::new(*u)).collect()),
|
||||
..Default::default()
|
||||
},
|
||||
error: r#"`string.lift_memory` read out of the memory bounds (index 13 > memory length 6)"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_lift_memory__invalid_encoding =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
InterfaceValue::I32(4),
|
||||
// ^^^^^^ length is too long
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new(vec![0, 159, 146, 150].iter().map(|b| Cell::new(*b)).collect::<Vec<Cell<u8>>>()),
|
||||
..Default::default()
|
||||
},
|
||||
error: r#"`string.lift_memory` invalid utf-8 sequence of 1 bytes from index 1"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_lift_memory__stack_is_too_small =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringLiftMemory,
|
||||
// ^^^^^^^^^^^^^^^^ `string.lift_memory` expects 2 values on the stack, only one is present.
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
InterfaceValue::I32(13),
|
||||
],
|
||||
instance: Instance::new(),
|
||||
error: r#"`string.lift_memory` needed to read `2` value(s) from the stack, but it doesn't contain enough data"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_memory =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringLowerMemory { allocator_index: 43 },
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
instance: Instance::new(),
|
||||
stack: [
|
||||
InterfaceValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
InterfaceValue::I32(13),
|
||||
// ^^^^^^^ length
|
||||
]
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_memory__roundtrip_with_memory_to_string =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringLowerMemory { allocator_index: 43 },
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::String("Hello, World!".into())],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_memory__allocator_does_not_exist =
|
||||
instructions: [Instruction::StringLowerMemory { allocator_index: 43 }],
|
||||
invocation_inputs: [],
|
||||
instance: Instance { ..Default::default() },
|
||||
error: r#"`string.lower_memory 43` the local or import function `43` doesn't exist"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_memory__stack_is_too_small =
|
||||
instructions: [
|
||||
Instruction::StringLowerMemory { allocator_index: 43 }
|
||||
// ^^ `43` expects 1 value on the stack, none is present
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
instance: Instance::new(),
|
||||
error: r#"`string.lower_memory 43` needed to read `1` value(s) from the stack, but it doesn't contain enough data"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_memory__failure_when_calling_the_allocator =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringLowerMemory { allocator_index: 153 }
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
instance: {
|
||||
let mut instance = Instance::new();
|
||||
instance.locals_or_imports.insert(
|
||||
153,
|
||||
LocalImport {
|
||||
inputs: vec![InterfaceType::I32],
|
||||
outputs: vec![InterfaceType::I32],
|
||||
function: |_| Err(()),
|
||||
// ^^^^^^^ function fails
|
||||
},
|
||||
);
|
||||
|
||||
instance
|
||||
},
|
||||
error: r#"`string.lower_memory 153` failed while calling the local or import function `153`"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_memory__invalid_allocator_signature =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringLowerMemory { allocator_index: 153 }
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
instance: {
|
||||
let mut instance = Instance::new();
|
||||
instance.locals_or_imports.insert(
|
||||
153,
|
||||
LocalImport {
|
||||
inputs: vec![InterfaceType::I32, InterfaceType::I32],
|
||||
outputs: vec![],
|
||||
function: |_| Err(()),
|
||||
},
|
||||
);
|
||||
|
||||
instance
|
||||
},
|
||||
error: r#"`string.lower_memory 153` the local or import function `153` has the signature `[I32] -> [I32]` but it received values of kind `[I32, I32] -> []`"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_size =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringSize,
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::String("Hello, World!".into()), InterfaceValue::I32(13)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_size__stack_is_too_small =
|
||||
instructions: [
|
||||
Instruction::StringSize,
|
||||
],
|
||||
invocation_inputs: [],
|
||||
instance: Instance::new(),
|
||||
error: r#"`string.size` needed to read `1` value(s) from the stack, but it doesn't contain enough data"#,
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_string_size__invalid_value_on_the_stack =
|
||||
instructions: [
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringSize,
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
error: r#"`string.size` read a value of type `I32` from the stack, but the type `String` was expected"#,
|
||||
);
|
||||
}
|
@ -188,61 +188,53 @@ where
|
||||
fn try_from(instructions: &Vec<Instruction>) -> Result<Self, Self::Error> {
|
||||
let executable_instructions = instructions
|
||||
.iter()
|
||||
.map(|instruction| {
|
||||
match instruction {
|
||||
Instruction::ArgumentGet { index } => {
|
||||
instructions::argument_get(*index, *instruction)
|
||||
}
|
||||
Instruction::CallCore { function_index } => {
|
||||
instructions::call_core(*function_index, *instruction)
|
||||
}
|
||||
Instruction::MemoryToString => instructions::memory_to_string(*instruction),
|
||||
Instruction::StringToMemory { allocator_index } => {
|
||||
instructions::string_to_memory(*allocator_index, *instruction)
|
||||
}
|
||||
|
||||
Instruction::I32ToS8 => instructions::i32_to_s8(*instruction),
|
||||
//Instruction::I32ToS8X
|
||||
Instruction::I32ToU8 => instructions::i32_to_u8(*instruction),
|
||||
Instruction::I32ToS16 => instructions::i32_to_s16(*instruction),
|
||||
//Instruction::I32ToS16X
|
||||
Instruction::I32ToU16 => instructions::i32_to_u16(*instruction),
|
||||
Instruction::I32ToS32 => instructions::i32_to_s32(*instruction),
|
||||
Instruction::I32ToU32 => instructions::i32_to_u32(*instruction),
|
||||
Instruction::I32ToS64 => instructions::i32_to_s64(*instruction),
|
||||
Instruction::I32ToU64 => instructions::i32_to_u64(*instruction),
|
||||
Instruction::I64ToS8 => instructions::i64_to_s8(*instruction),
|
||||
//Instruction::I64ToS8X
|
||||
Instruction::I64ToU8 => instructions::i64_to_u8(*instruction),
|
||||
Instruction::I64ToS16 => instructions::i64_to_s16(*instruction),
|
||||
//Instruction::I64ToS16X
|
||||
Instruction::I64ToU16 => instructions::i64_to_u16(*instruction),
|
||||
Instruction::I64ToS32 => instructions::i64_to_s32(*instruction),
|
||||
Instruction::I64ToU32 => instructions::i64_to_u32(*instruction),
|
||||
Instruction::I64ToS64 => instructions::i64_to_s64(*instruction),
|
||||
Instruction::I64ToU64 => instructions::i64_to_u64(*instruction),
|
||||
Instruction::S8ToI32 => instructions::s8_to_i32(*instruction),
|
||||
Instruction::U8ToI32 => instructions::u8_to_i32(*instruction),
|
||||
Instruction::S16ToI32 => instructions::s16_to_i32(*instruction),
|
||||
Instruction::U16ToI32 => instructions::u16_to_i32(*instruction),
|
||||
Instruction::S32ToI32 => instructions::s32_to_i32(*instruction),
|
||||
Instruction::U32ToI32 => instructions::u32_to_i32(*instruction),
|
||||
Instruction::S64ToI32 | Instruction::S64ToI32X => {
|
||||
instructions::s64_to_i32(*instruction)
|
||||
}
|
||||
Instruction::U64ToI32 | Instruction::U64ToI32X => {
|
||||
instructions::u64_to_i32(*instruction)
|
||||
}
|
||||
Instruction::S8ToI64 => instructions::s8_to_i64(*instruction),
|
||||
Instruction::U8ToI64 => instructions::u8_to_i64(*instruction),
|
||||
Instruction::S16ToI64 => instructions::s16_to_i64(*instruction),
|
||||
Instruction::U16ToI64 => instructions::u16_to_i64(*instruction),
|
||||
Instruction::S32ToI64 => instructions::s32_to_i64(*instruction),
|
||||
Instruction::U32ToI64 => instructions::u32_to_i64(*instruction),
|
||||
Instruction::S64ToI64 => instructions::s64_to_i64(*instruction),
|
||||
Instruction::U64ToI64 => instructions::u64_to_i64(*instruction),
|
||||
_ => unimplemented!(),
|
||||
.map(|instruction| match instruction {
|
||||
Instruction::ArgumentGet { index } => {
|
||||
instructions::argument_get(*index, *instruction)
|
||||
}
|
||||
|
||||
Instruction::CallCore { function_index } => {
|
||||
instructions::call_core(*function_index, *instruction)
|
||||
}
|
||||
|
||||
Instruction::S8FromI32 => instructions::s8_from_i32(*instruction),
|
||||
Instruction::S8FromI64 => instructions::s8_from_i64(*instruction),
|
||||
Instruction::S16FromI32 => instructions::s16_from_i32(*instruction),
|
||||
Instruction::S16FromI64 => instructions::s16_from_i64(*instruction),
|
||||
Instruction::S32FromI32 => instructions::s32_from_i32(*instruction),
|
||||
Instruction::S32FromI64 => instructions::s32_from_i64(*instruction),
|
||||
Instruction::S64FromI32 => instructions::s64_from_i32(*instruction),
|
||||
Instruction::S64FromI64 => instructions::s64_from_i64(*instruction),
|
||||
Instruction::I32FromS8 => instructions::i32_from_s8(*instruction),
|
||||
Instruction::I32FromS16 => instructions::i32_from_s16(*instruction),
|
||||
Instruction::I32FromS32 => instructions::i32_from_s32(*instruction),
|
||||
Instruction::I32FromS64 => instructions::i32_from_s64(*instruction),
|
||||
Instruction::I64FromS8 => instructions::i64_from_s8(*instruction),
|
||||
Instruction::I64FromS16 => instructions::i64_from_s16(*instruction),
|
||||
Instruction::I64FromS32 => instructions::i64_from_s32(*instruction),
|
||||
Instruction::I64FromS64 => instructions::i64_from_s64(*instruction),
|
||||
Instruction::U8FromI32 => instructions::u8_from_i32(*instruction),
|
||||
Instruction::U8FromI64 => instructions::u8_from_i64(*instruction),
|
||||
Instruction::U16FromI32 => instructions::u16_from_i32(*instruction),
|
||||
Instruction::U16FromI64 => instructions::u16_from_i64(*instruction),
|
||||
Instruction::U32FromI32 => instructions::u32_from_i32(*instruction),
|
||||
Instruction::U32FromI64 => instructions::u32_from_i64(*instruction),
|
||||
Instruction::U64FromI32 => instructions::u64_from_i32(*instruction),
|
||||
Instruction::U64FromI64 => instructions::u64_from_i64(*instruction),
|
||||
Instruction::I32FromU8 => instructions::i32_from_u8(*instruction),
|
||||
Instruction::I32FromU16 => instructions::i32_from_u16(*instruction),
|
||||
Instruction::I32FromU32 => instructions::i32_from_u32(*instruction),
|
||||
Instruction::I32FromU64 => instructions::i32_from_u64(*instruction),
|
||||
Instruction::I64FromU8 => instructions::i64_from_u8(*instruction),
|
||||
Instruction::I64FromU16 => instructions::i64_from_u16(*instruction),
|
||||
Instruction::I64FromU32 => instructions::i64_from_u32(*instruction),
|
||||
Instruction::I64FromU64 => instructions::i64_from_u64(*instruction),
|
||||
|
||||
Instruction::StringLiftMemory => instructions::string_lift_memory(*instruction),
|
||||
Instruction::StringLowerMemory { allocator_index } => {
|
||||
instructions::string_lower_memory(*allocator_index, *instruction)
|
||||
}
|
||||
Instruction::StringSize => instructions::string_size(*instruction),
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -22,9 +22,13 @@ pub trait Stackable {
|
||||
|
||||
/// Removes `n` elements from the end of the stack, `None` if the
|
||||
/// stack doesn't contain enough elements.
|
||||
/// Returned items are ordered by FIFO: the last element comes
|
||||
/// first in the list.
|
||||
/// Returned items are in reverse order: the last element comes
|
||||
/// last in the list.
|
||||
fn pop(&mut self, n: usize) -> Option<Vec<Self::Item>>;
|
||||
|
||||
/// Peek the last item of the stack and returns a reference to it,
|
||||
/// `None` if the stack is empty.
|
||||
fn peek1(&self) -> Option<&Self::Item>;
|
||||
}
|
||||
|
||||
/// A stack implementation of the `Stackable` trait, based on a vector.
|
||||
@ -78,7 +82,6 @@ where
|
||||
let items = self
|
||||
.inner
|
||||
.drain(self.inner.len() - n..)
|
||||
.rev()
|
||||
.collect::<Vec<Self::Item>>();
|
||||
|
||||
assert!(items.len() == n);
|
||||
@ -86,6 +89,14 @@ where
|
||||
Some(items)
|
||||
}
|
||||
}
|
||||
|
||||
fn peek1(&self) -> Option<&Self::Item> {
|
||||
if self.inner.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(&self.inner[self.inner.len() - 1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -121,10 +132,19 @@ mod tests {
|
||||
stack.push(6);
|
||||
|
||||
assert_eq!(stack.pop(1), Some(vec![6]));
|
||||
assert_eq!(stack.pop(2), Some(vec![5, 4]));
|
||||
assert_eq!(stack.pop(2), Some(vec![4, 5]));
|
||||
assert_eq!(stack.pop(4), None); // not enough items
|
||||
assert_eq!(stack.pop(3), Some(vec![3, 2, 1]));
|
||||
assert_eq!(stack.pop(3), Some(vec![1, 2, 3]));
|
||||
assert_eq!(stack.pop1(), None);
|
||||
assert_eq!(stack.is_empty(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peek1() {
|
||||
let mut stack = Stack::new();
|
||||
stack.push(1);
|
||||
stack.push(2);
|
||||
|
||||
assert_eq!(stack.peek1(), Some(&2));
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ impl BackendCompilerConfig {
|
||||
}
|
||||
|
||||
/// Configuration data for the compiler
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug)]
|
||||
pub struct CompilerConfig {
|
||||
/// Symbol information generated from emscripten; used for more detailed debug messages
|
||||
pub symbol_map: Option<HashMap<u32, String>>,
|
||||
@ -136,6 +136,13 @@ pub struct CompilerConfig {
|
||||
/// Enabling this makes execution deterministic but increases runtime overhead.
|
||||
pub nan_canonicalization: bool,
|
||||
|
||||
/// Turns on verification that is done by default when `debug_assertions` are enabled
|
||||
/// (for example in 'debug' builds). Disabling this flag will make compilation faster
|
||||
/// in debug mode at the cost of not detecting bugs in the compiler.
|
||||
///
|
||||
/// These verifications are disabled by default in 'release' builds.
|
||||
pub enable_verification: bool,
|
||||
|
||||
pub features: Features,
|
||||
|
||||
// Target info. Presently only supported by LLVM.
|
||||
@ -148,6 +155,30 @@ pub struct CompilerConfig {
|
||||
pub generate_debug_info: bool,
|
||||
}
|
||||
|
||||
impl Default for CompilerConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
symbol_map: Default::default(),
|
||||
memory_bound_check_mode: Default::default(),
|
||||
enforce_stack_check: Default::default(),
|
||||
track_state: Default::default(),
|
||||
full_preemption: Default::default(),
|
||||
nan_canonicalization: Default::default(),
|
||||
features: Default::default(),
|
||||
triple: Default::default(),
|
||||
cpu_name: Default::default(),
|
||||
cpu_features: Default::default(),
|
||||
backend_specific_config: Default::default(),
|
||||
generate_debug_info: Default::default(),
|
||||
|
||||
// Default verification to 'on' when testing or running in debug mode.
|
||||
// NOTE: cfg(test) probably does nothing when not running `cargo test`
|
||||
// on this crate
|
||||
enable_verification: cfg!(test) || cfg!(debug_assertions),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CompilerConfig {
|
||||
/// Use this to check if we should be generating debug information.
|
||||
/// This function takes into account the features that runtime-core was
|
||||
|
@ -337,6 +337,7 @@ mod tests {
|
||||
threads: true,
|
||||
},
|
||||
nan_canonicalization: true,
|
||||
enable_verification: true,
|
||||
..Default::default()
|
||||
};
|
||||
let module = compile_with_config(&module.into_vec(), config)
|
||||
@ -776,6 +777,7 @@ mod tests {
|
||||
threads: true,
|
||||
},
|
||||
nan_canonicalization: true,
|
||||
enable_verification: true,
|
||||
..Default::default()
|
||||
};
|
||||
compile_with_config(&module.into_vec(), config)
|
||||
@ -829,6 +831,7 @@ mod tests {
|
||||
threads: true,
|
||||
},
|
||||
nan_canonicalization: true,
|
||||
enable_verification: true,
|
||||
..Default::default()
|
||||
};
|
||||
compile_with_config(&module.into_vec(), config)
|
||||
@ -881,6 +884,7 @@ mod tests {
|
||||
threads: true,
|
||||
},
|
||||
nan_canonicalization: true,
|
||||
enable_verification: true,
|
||||
..Default::default()
|
||||
};
|
||||
let module = compile_with_config(&module.into_vec(), config)
|
||||
@ -977,6 +981,7 @@ mod tests {
|
||||
threads: true,
|
||||
},
|
||||
nan_canonicalization: true,
|
||||
enable_verification: true,
|
||||
..Default::default()
|
||||
};
|
||||
let module = compile_with_config(&module.into_vec(), config)
|
||||
|
Loading…
Reference in New Issue
Block a user