Skip to content

Commit

Permalink
Add support for sign extension instructions.
Browse files Browse the repository at this point in the history
Proposal https://github.com/WebAssembly/sign-extension-ops added
the following instructions for sign-extending integers:

    0xC0 i32.extend8_s
    0xC1 i32.extend16_s
    0xC2 i64.extend8_s
    0xC3 i64.extend16_s
    0xC4 i64.extend32_s

These instructions are now in widespread use, including in WASM
generated by LLVM (e.g. when compiling Rust).
  • Loading branch information
jmillikin committed Nov 17, 2023
1 parent 48050b1 commit 74e37b4
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 0 deletions.
11 changes: 11 additions & 0 deletions wain-ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,11 @@ pub enum InsnKind {
I64ReinterpretF64,
F32ReinterpretI32,
F64ReinterpretI64,
I32Extend8S,
I32Extend16S,
I64Extend8S,
I64Extend16S,
I64Extend32S,
}

impl InsnKind {
Expand Down Expand Up @@ -576,6 +581,12 @@ impl InsnKind {
I64ReinterpretF64 => "i64.reinterpret_f64",
F32ReinterpretI32 => "f32.reinterpret_i32",
F64ReinterpretI64 => "f64.reinterpret_i64",
// sign extension
I32Extend8S => "i32.extend8_s",
I32Extend16S => "i32.extend16_s",
I64Extend8S => "i64.extend8_s",
I64Extend16S => "i64.extend16_s",
I64Extend32S => "i64.extend32_s",
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions wain-exec/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,12 @@ impl<'m, 's, I: Importer> Execute<'m, 's, I> for ast::Instruction {
I64ReinterpretF64 => runtime.stack.write_top_type(i64::VAL_TYPE),
F32ReinterpretI32 => runtime.stack.write_top_type(f32::VAL_TYPE),
F64ReinterpretI64 => runtime.stack.write_top_type(f64::VAL_TYPE),
// https://webassembly.github.io/spec/core/exec/numerics.html#op-iextendn-s
I32Extend8S => runtime.cvtop(|v: i32| i32::from(v as i8)),
I32Extend16S => runtime.cvtop(|v: i32| i32::from(v as i16)),
I64Extend8S => runtime.cvtop(|v: i64| i64::from(v as i8)),
I64Extend16S => runtime.cvtop(|v: i64| i64::from(v as i16)),
I64Extend32S => runtime.cvtop(|v: i64| i64::from(v as i32)),
}
Ok(ExecState::Continue)
}
Expand Down
6 changes: 6 additions & 0 deletions wain-syntax-binary/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,12 @@ impl<'s> Parse<'s> for Instruction {
0xbd => I64ReinterpretF64,
0xbe => F32ReinterpretI32,
0xbf => F64ReinterpretI64,
// sign extension
0xc0 => I32Extend8S,
0xc1 => I32Extend16S,
0xc2 => I64Extend8S,
0xc3 => I64Extend16S,
0xc4 => I64Extend32S,
// https://webassembly.github.io/spec/core/binary/instructions.html#numeric-instructions
b => return Err(parser.unexpected_byte([], b, "instruction")),
};
Expand Down
6 changes: 6 additions & 0 deletions wain-syntax-text/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,12 @@ pub enum InsnKind<'s> {
I64ReinterpretF64,
F32ReinterpretI32,
F64ReinterpretI64,
// Sign extension
I32Extend8S,
I32Extend16S,
I64Extend8S,
I64Extend16S,
I64Extend32S,
}

impl<'s> InsnKind<'s> {
Expand Down
10 changes: 10 additions & 0 deletions wain-syntax-text/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1916,6 +1916,11 @@ impl<'s, 'p> MaybeFoldedInsn<'s, 'p> {
"i64.reinterpret_f64" => InsnKind::I64ReinterpretF64,
"f32.reinterpret_i32" => InsnKind::F32ReinterpretI32,
"f64.reinterpret_i64" => InsnKind::F64ReinterpretI64,
"i32.extend8_s" => InsnKind::I32Extend8S,
"i32.extend16_s" => InsnKind::I32Extend16S,
"i64.extend8_s" => InsnKind::I64Extend8S,
"i64.extend16_s" => InsnKind::I64Extend16S,
"i64.extend32_s" => InsnKind::I64Extend32S,
_ => return self.parser.error(ParseErrorKind::UnexpectedKeyword(kw), start),
};
Ok(Instruction { start, kind })
Expand Down Expand Up @@ -4394,6 +4399,11 @@ mod tests {
assert_insn!(r#"i64.reinterpret_f64"#, [I64ReinterpretF64]);
assert_insn!(r#"f32.reinterpret_i32"#, [F32ReinterpretI32]);
assert_insn!(r#"f64.reinterpret_i64"#, [F64ReinterpretI64]);
assert_insn!(r#"i32.extend8_s"#, [I32Extend8S]);
assert_insn!(r#"i32.extend16_s"#, [I32Extend16S]);
assert_insn!(r#"i64.extend8_s"#, [I64Extend8S]);
assert_insn!(r#"i64.extend16_s"#, [I64Extend16S]);
assert_insn!(r#"i64.extend32_s"#, [I64Extend32S]);
}

#[test]
Expand Down
6 changes: 6 additions & 0 deletions wain-syntax-text/src/wat2wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,12 @@ impl<'s> Transform<'s> for wat::Instruction<'s> {
wat::InsnKind::I64ReinterpretF64 => wasm::InsnKind::I64ReinterpretF64,
wat::InsnKind::F32ReinterpretI32 => wasm::InsnKind::F32ReinterpretI32,
wat::InsnKind::F64ReinterpretI64 => wasm::InsnKind::F64ReinterpretI64,
// Sign extension
wat::InsnKind::I32Extend8S => wasm::InsnKind::I32Extend8S,
wat::InsnKind::I32Extend16S => wasm::InsnKind::I32Extend16S,
wat::InsnKind::I64Extend8S => wasm::InsnKind::I64Extend8S,
wat::InsnKind::I64Extend16S => wasm::InsnKind::I64Extend16S,
wat::InsnKind::I64Extend32S => wasm::InsnKind::I64Extend32S,
};
Ok(wasm::Instruction { start, kind })
}
Expand Down
6 changes: 6 additions & 0 deletions wain-validate/src/insn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,12 @@ impl<'outer, 'm, 's, S: Source> ValidateInsnSeq<'outer, 'm, 's, S> for Instructi
F64Abs | F64Neg | F64Ceil | F64Floor | F64Trunc | F64Nearest | F64Sqrt => {
ctx.ensure_op_stack_top(ValType::F64)?;
}
I32Extend8S | I32Extend16S => {
ctx.ensure_op_stack_top(ValType::I32)?;
}
I64Extend8S | I64Extend16S | I64Extend32S => {
ctx.ensure_op_stack_top(ValType::I64)?;
}
// https://webassembly.github.io/spec/core/valid/instructions.html#valid-binop
// [t t] -> [t]
I32Add | I32Sub | I32Mul | I32DivS | I32DivU | I32RemS | I32RemU | I32And | I32Or | I32Xor | I32Shl
Expand Down

0 comments on commit 74e37b4

Please sign in to comment.