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 post-MVP WASM ops (sign-ext and mutable-globals), fix #968. #979

Merged
merged 2 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions soroban-env-host/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod ledger;
mod lifecycle;
mod map;
mod num;
mod post_mvp;
mod prng;
mod storage;
mod str;
Expand Down
41 changes: 41 additions & 0 deletions soroban-env-host/src/test/post_mvp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::{Env, EnvBase, Host, HostError, Symbol, Tag, TryFromVal};
use soroban_synth_wasm::{Arity, ModEmitter};

// Emit a wasm module that uses post-MVP WASM features. Specifically
// mutable-globals and sign-ext.
fn post_mvp_wasm_module() -> Vec<u8> {
let mut me = ModEmitter::new();

// Emit an exported mutable global
me.define_global_i64(-100, true, Some("global"));

let mut fe = me.func(Arity(0), 0);
fe.i64_const(0x0000_0000_ffff_abcd_u64 as i64);

// Emit an op from the new sign-ext repertoire
fe.i64_extend32s();

// Turn this into a I64Small
fe.i64_const(8);
fe.i64_shl();
fe.i64_const(Tag::I64Small as i64);
fe.i64_or();

fe.finish_and_export("test").finish()
}

#[test]
fn test_enabled_post_mvp_features() -> Result<(), HostError> {
let wasm = post_mvp_wasm_module();
let host = Host::test_host_with_recording_footprint();
host.enable_debug()?;
let addr = host.register_test_contract_wasm(wasm.as_slice());
let res = host.call(
addr,
Symbol::try_from_small_str("test")?,
host.vec_new_from_slice(&[])?,
)?;
let res_i64 = i64::try_from_val(&host, &res)?;
assert_eq!(res_i64, 0xffff_ffff_ffff_abcd_u64 as i64);
Ok(())
}
4 changes: 2 additions & 2 deletions soroban-env-host/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ impl Vm {
// Turn off all optional wasm features.
config
.wasm_multi_value(false)
.wasm_mutable_global(false)
.wasm_mutable_global(true)
.wasm_saturating_float_to_int(false)
.wasm_sign_extension(false)
.wasm_sign_extension(true)
.floats(false)
.consume_fuel(true)
.fuel_consumption_mode(FuelConsumptionMode::Eager)
Expand Down
4 changes: 3 additions & 1 deletion soroban-synth-wasm/src/func_emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,5 +349,7 @@ i64_numeric_insn!(
(i64_shr_s, I64ShrS),
(i64_shr_u, I64ShrU),
(i64_rotl, I64Rotl),
(i64_rotr, I64Rotr)
(i64_rotr, I64Rotr),
// post-MVP instructions
(i64_extend32s, I64Extend32S)
);
20 changes: 17 additions & 3 deletions soroban-synth-wasm/src/mod_emitter.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::FuncEmitter;
use std::collections::HashMap;
use wasm_encoder::{
CodeSection, ConstExpr, CustomSection, ElementSection, Elements, EntityType, ExportSection,
Function, FunctionSection, GlobalSection, GlobalType, ImportSection, MemorySection, MemoryType,
Module, TableSection, TableType, TypeSection, ValType,
CodeSection, ConstExpr, CustomSection, ElementSection, Elements, EntityType, ExportKind,
ExportSection, Function, FunctionSection, GlobalSection, GlobalType, ImportSection,
MemorySection, MemoryType, Module, TableSection, TableType, TypeSection, ValType,
};

/// Wrapper for a u32 that defines the arity of a function -- that is, the number of
Expand Down Expand Up @@ -187,6 +187,20 @@ impl ModEmitter {
.active(Some(table_index), &offset, element_type, functions);
}

pub fn define_global_i64(&mut self, val: i64, mutable: bool, export: Option<&str>) {
let idx = self.globals.len();
self.globals.global(
GlobalType {
val_type: ValType::I64,
mutable,
},
&ConstExpr::i64_const(val),
);
if let Some(name) = export {
self.exports.export(name, ExportKind::Global, idx);
}
}

/// Finish emitting code, consuming the `self`, serializing a WASM binary
/// blob, validating and returning it. Panics the resulting blob fails
/// validation.
Expand Down