Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable sign ext proposal support #4

Merged
merged 17 commits into from
Sep 9, 2024
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
Cargo.lock
spec/target
.idea
.direnv
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ exclude = [ "/res/*", "/tests/*", "/fuzz/*", "/benches/*" ]
[dependencies]
casper-wasmi-core = { version = "0.2.1", path = "core", default-features = false }
validation = { package = "casper-wasmi-validation", version = "0.5.0", path = "validation", default-features = false }
casper-wasm = { version = "0.46.0", default-features = false }
casper-wasm = { version = "0.46.0", default-features = false, features = ["sign_ext"] }

[dev-dependencies]
assert_matches = "1.5"
Expand Down
20 changes: 10 additions & 10 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use casper_wasmi::{
use clap::Parser;
use core::fmt::Write;
use std::fs;
use wasmi_v1 as wasmi;
use wasmi_v1 as casper_wasmi;

/// Simple program to greet a person
#[derive(Parser, Debug)]
Expand Down Expand Up @@ -87,12 +87,12 @@ fn load_wasm_func(
wasm_bytes: &[u8],
func_name: &str,
) -> Result<(Func, Store<()>)> {
let engine = wasmi::Engine::default();
let mut store = wasmi::Store::new(&engine, ());
let module = wasmi::Module::new(&engine, &mut &wasm_bytes[..]).map_err(|error| {
let engine = casper_wasmi::Engine::default();
let mut store = casper_wasmi::Store::new(&engine, ());
let module = casper_wasmi::Module::new(&engine, &mut &wasm_bytes[..]).map_err(|error| {
anyhow!("failed to parse and validate Wasm module {wasm_file}: {error}")
})?;
let mut linker = <wasmi::Linker<()>>::new();
let mut linker = <casper_wasmi::Linker<()>>::new();
let instance = linker
.instantiate(&mut store, &module)
.and_then(|pre| pre.start(&mut store))
Expand All @@ -113,8 +113,8 @@ fn load_wasm_func(

/// Returns a [`Vec`] of `(&str, FuncType)` describing the exported functions of the [`Module`].
///
/// [`Module`]: [`wasmi::Module`]
fn exported_funcs(module: &wasmi::Module) -> Vec<(&str, FuncType)> {
/// [`Module`]: [`casper_wasmi::Module`]
fn exported_funcs(module: &casper_wasmi::Module) -> Vec<(&str, FuncType)> {
module
.exports()
.filter_map(|export| {
Expand All @@ -129,8 +129,8 @@ fn exported_funcs(module: &wasmi::Module) -> Vec<(&str, FuncType)> {

/// Returns a [`String`] displaying a list of exported functions from the [`Module`].
///
/// [`Module`]: [`wasmi::Module`]
fn display_exported_funcs(module: &wasmi::Module) -> String {
/// [`Module`]: [`casper_wasmi::Module`]
fn display_exported_funcs(module: &casper_wasmi::Module) -> String {
let exported_funcs = exported_funcs(module)
.into_iter()
.map(|(name, func_type)| display_exported_func(name, &func_type));
Expand Down Expand Up @@ -241,7 +241,7 @@ fn print_execution_start(wasm_file: &str, func_name: &str, func_args: &[Value])
println!(") ...");
}

/// Prints the results of the Wasm computation in a human readable form.
/// Prints the results of the Wasm computation in a human-readable form.
fn print_pretty_results(results: &[Value]) {
let pretty_results = results
.iter()
Expand Down
18 changes: 18 additions & 0 deletions src/isa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,12 @@ pub enum Instruction<'a> {
I64ReinterpretF64,
F32ReinterpretI32,
F64ReinterpretI64,

I32Extend8S,
I32Extend16S,
I64Extend8S,
I64Extend16S,
I64Extend32S,
}

/// The internally-stored instruction type. This differs from `Instruction` in that the `BrTable`
Expand Down Expand Up @@ -533,6 +539,12 @@ pub(crate) enum InstructionInternal {
I64ReinterpretF64,
F32ReinterpretI32,
F64ReinterpretI64,

I32Extend8S,
I32Extend16S,
I64Extend8S,
I64Extend16S,
I64Extend32S,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -789,6 +801,12 @@ impl<'a> Iterator for InstructionIter<'a> {
InstructionInternal::I64ReinterpretF64 => Instruction::I64ReinterpretF64,
InstructionInternal::F32ReinterpretI32 => Instruction::F32ReinterpretI32,
InstructionInternal::F64ReinterpretI64 => Instruction::F64ReinterpretI64,

InstructionInternal::I32Extend8S => Instruction::I32Extend8S,
InstructionInternal::I32Extend16S => Instruction::I32Extend16S,
InstructionInternal::I64Extend8S => Instruction::I64Extend8S,
InstructionInternal::I64Extend16S => Instruction::I64Extend16S,
InstructionInternal::I64Extend32S => Instruction::I64Extend32S,
};

self.position += 1;
Expand Down
109 changes: 71 additions & 38 deletions src/prepare/compile.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use alloc::{string::String, vec::Vec};

use casper_wasm::elements::{BlockType, FuncBody, Instruction};
use casper_wasm::elements::{BlockType, FuncBody, Instruction, SignExtInstruction};

use crate::isa;
use validation::{
Expand Down Expand Up @@ -111,7 +111,7 @@ impl Compiler {
) -> Result<(), Error> {
use self::Instruction::*;

match *instruction {
match instruction {
Unreachable => {
self.sink.emit(isa::InstructionInternal::Unreachable);
context.step(instruction)?;
Expand Down Expand Up @@ -226,7 +226,7 @@ impl Compiler {
}
Br(depth) => {
let target = require_target(
depth,
*depth,
context.value_stack.len(),
&context.frame_stack,
&self.label_stack,
Expand All @@ -246,7 +246,7 @@ impl Compiler {
context.step(instruction)?;

let target = require_target(
depth,
*depth,
context.value_stack.len(),
&context.frame_stack,
&self.label_stack,
Expand Down Expand Up @@ -312,12 +312,12 @@ impl Compiler {
}
Call(index) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::Call(index));
self.sink.emit(isa::InstructionInternal::Call(*index));
}
CallIndirect(index, _reserved) => {
context.step(instruction)?;
self.sink
.emit(isa::InstructionInternal::CallIndirect(index));
.emit(isa::InstructionInternal::CallIndirect(*index));
}

Drop => {
Expand All @@ -332,121 +332,130 @@ impl Compiler {
GetLocal(index) => {
// We need to calculate relative depth before validation since
// it will change the value stack size.
let depth = relative_local_depth(index, &context.locals, &context.value_stack)?;
let depth = relative_local_depth(*index, &context.locals, &context.value_stack)?;
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::GetLocal(depth));
}
SetLocal(index) => {
context.step(instruction)?;
let depth = relative_local_depth(index, &context.locals, &context.value_stack)?;
let depth = relative_local_depth(*index, &context.locals, &context.value_stack)?;
self.sink.emit(isa::InstructionInternal::SetLocal(depth));
}
TeeLocal(index) => {
context.step(instruction)?;
let depth = relative_local_depth(index, &context.locals, &context.value_stack)?;
let depth = relative_local_depth(*index, &context.locals, &context.value_stack)?;
self.sink.emit(isa::InstructionInternal::TeeLocal(depth));
}
GetGlobal(index) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::GetGlobal(index));
self.sink.emit(isa::InstructionInternal::GetGlobal(*index));
}
SetGlobal(index) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::SetGlobal(index));
self.sink.emit(isa::InstructionInternal::SetGlobal(*index));
}

I32Load(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I32Load(offset));
self.sink.emit(isa::InstructionInternal::I32Load(*offset));
}
I64Load(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Load(offset));
self.sink.emit(isa::InstructionInternal::I64Load(*offset));
}
F32Load(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::F32Load(offset));
self.sink.emit(isa::InstructionInternal::F32Load(*offset));
}
F64Load(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::F64Load(offset));
self.sink.emit(isa::InstructionInternal::F64Load(*offset));
}
I32Load8S(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I32Load8S(offset));
self.sink.emit(isa::InstructionInternal::I32Load8S(*offset));
}
I32Load8U(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I32Load8U(offset));
self.sink.emit(isa::InstructionInternal::I32Load8U(*offset));
}
I32Load16S(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I32Load16S(offset));
self.sink
.emit(isa::InstructionInternal::I32Load16S(*offset));
}
I32Load16U(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I32Load16U(offset));
self.sink
.emit(isa::InstructionInternal::I32Load16U(*offset));
}
I64Load8S(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Load8S(offset));
self.sink.emit(isa::InstructionInternal::I64Load8S(*offset));
}
I64Load8U(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Load8U(offset));
self.sink.emit(isa::InstructionInternal::I64Load8U(*offset));
}
I64Load16S(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Load16S(offset));
self.sink
.emit(isa::InstructionInternal::I64Load16S(*offset));
}
I64Load16U(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Load16U(offset));
self.sink
.emit(isa::InstructionInternal::I64Load16U(*offset));
}
I64Load32S(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Load32S(offset));
self.sink
.emit(isa::InstructionInternal::I64Load32S(*offset));
}
I64Load32U(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Load32U(offset));
self.sink
.emit(isa::InstructionInternal::I64Load32U(*offset));
}

I32Store(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I32Store(offset));
self.sink.emit(isa::InstructionInternal::I32Store(*offset));
}
I64Store(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Store(offset));
self.sink.emit(isa::InstructionInternal::I64Store(*offset));
}
F32Store(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::F32Store(offset));
self.sink.emit(isa::InstructionInternal::F32Store(*offset));
}
F64Store(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::F64Store(offset));
self.sink.emit(isa::InstructionInternal::F64Store(*offset));
}
I32Store8(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I32Store8(offset));
self.sink.emit(isa::InstructionInternal::I32Store8(*offset));
}
I32Store16(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I32Store16(offset));
self.sink
.emit(isa::InstructionInternal::I32Store16(*offset));
}
I64Store8(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Store8(offset));
self.sink.emit(isa::InstructionInternal::I64Store8(*offset));
}
I64Store16(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Store16(offset));
self.sink
.emit(isa::InstructionInternal::I64Store16(*offset));
}
I64Store32(_, offset) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Store32(offset));
self.sink
.emit(isa::InstructionInternal::I64Store32(*offset));
}

CurrentMemory(_) => {
Expand All @@ -460,19 +469,19 @@ impl Compiler {

I32Const(v) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I32Const(v));
self.sink.emit(isa::InstructionInternal::I32Const(*v));
}
I64Const(v) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Const(v));
self.sink.emit(isa::InstructionInternal::I64Const(*v));
}
F32Const(v) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::F32Const(v));
self.sink.emit(isa::InstructionInternal::F32Const(*v));
}
F64Const(v) => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::F64Const(v));
self.sink.emit(isa::InstructionInternal::F64Const(*v));
}

I32Eqz => {
Expand Down Expand Up @@ -976,6 +985,30 @@ impl Compiler {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::F64ReinterpretI64);
}

SignExt(sign_ext_instruction) => match sign_ext_instruction {
SignExtInstruction::I32Extend8S => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I32Extend8S);
}
SignExtInstruction::I32Extend16S => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I32Extend16S);
}
SignExtInstruction::I64Extend8S => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Extend8S);
}
SignExtInstruction::I64Extend16S => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Extend16S);
}
SignExtInstruction::I64Extend32S => {
context.step(instruction)?;
self.sink.emit(isa::InstructionInternal::I64Extend32S);
}
},

_ => {
context.step(instruction)?;
}
Expand Down
Loading