mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-13 23:11:53 +00:00
continue env module implementation
This commit is contained in:
@ -2,7 +2,7 @@ use std::io;
|
|||||||
use super::{Deserialize, Serialize, Error, VarUint7, VarUint32};
|
use super::{Deserialize, Serialize, Error, VarUint7, VarUint32};
|
||||||
|
|
||||||
/// Internal reference of the exported entry.
|
/// Internal reference of the exported entry.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Internal {
|
pub enum Internal {
|
||||||
/// Function reference.
|
/// Function reference.
|
||||||
Function(u32),
|
Function(u32),
|
||||||
@ -48,6 +48,7 @@ impl Serialize for Internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Export entry.
|
/// Export entry.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct ExportEntry {
|
pub struct ExportEntry {
|
||||||
field_str: String,
|
field_str: String,
|
||||||
internal: Internal,
|
internal: Internal,
|
||||||
|
@ -5,6 +5,7 @@ use super::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Global definition struct
|
/// Global definition struct
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct GlobalType {
|
pub struct GlobalType {
|
||||||
content_type: ValueType,
|
content_type: ValueType,
|
||||||
is_mutable: bool,
|
is_mutable: bool,
|
||||||
@ -50,6 +51,7 @@ impl Serialize for GlobalType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Table entry
|
/// Table entry
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct TableType {
|
pub struct TableType {
|
||||||
elem_type: i8,
|
elem_type: i8,
|
||||||
limits: ResizableLimits,
|
limits: ResizableLimits,
|
||||||
@ -144,6 +146,7 @@ impl Serialize for ResizableLimits {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Memory entry.
|
/// Memory entry.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct MemoryType(ResizableLimits);
|
pub struct MemoryType(ResizableLimits);
|
||||||
|
|
||||||
impl MemoryType {
|
impl MemoryType {
|
||||||
@ -174,6 +177,7 @@ impl Serialize for MemoryType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// External to local binding.
|
/// External to local binding.
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum External {
|
pub enum External {
|
||||||
/// Binds to function with index.
|
/// Binds to function with index.
|
||||||
Function(u32),
|
Function(u32),
|
||||||
@ -230,6 +234,7 @@ impl Serialize for External {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Import entry.
|
/// Import entry.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct ImportEntry {
|
pub struct ImportEntry {
|
||||||
module_str: String,
|
module_str: String,
|
||||||
field_str: String,
|
field_str: String,
|
||||||
|
@ -220,7 +220,7 @@ impl Serialize for TypeSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Section of the imports definition.
|
/// Section of the imports definition.
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ImportSection(Vec<ImportEntry>);
|
pub struct ImportSection(Vec<ImportEntry>);
|
||||||
|
|
||||||
impl ImportSection {
|
impl ImportSection {
|
||||||
@ -444,7 +444,7 @@ impl Serialize for GlobalSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// List of exports definition.
|
/// List of exports definition.
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ExportSection(Vec<ExportEntry>);
|
pub struct ExportSection(Vec<ExportEntry>);
|
||||||
|
|
||||||
impl ExportSection {
|
impl ExportSection {
|
||||||
|
@ -2,6 +2,7 @@ use std::io;
|
|||||||
use super::{Deserialize, Serialize, Error, VarUint32, CountedList, InitExpr, CountedListWriter};
|
use super::{Deserialize, Serialize, Error, VarUint32, CountedList, InitExpr, CountedListWriter};
|
||||||
|
|
||||||
/// Entry in the element section.
|
/// Entry in the element section.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct ElementSegment {
|
pub struct ElementSegment {
|
||||||
index: u32,
|
index: u32,
|
||||||
offset: InitExpr,
|
offset: InitExpr,
|
||||||
|
@ -1,18 +1,33 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use builder::module;
|
use builder::module;
|
||||||
use elements::{Module, FunctionType, ExportEntry, Internal, MemoryType};
|
use elements::{Module, FunctionType, ExportEntry, Internal, MemoryType, GlobalEntry, GlobalType,
|
||||||
|
ValueType, InitExpr, TableType, Opcode};
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
use interpreter::module::{ModuleInstanceInterface, ItemIndex, CallerContext};
|
use interpreter::module::{ModuleInstanceInterface, ItemIndex, CallerContext};
|
||||||
use interpreter::memory::MemoryInstance;
|
use interpreter::memory::MemoryInstance;
|
||||||
use interpreter::table::TableInstance;
|
use interpreter::table::TableInstance;
|
||||||
use interpreter::value::RuntimeValue;
|
use interpreter::value::RuntimeValue;
|
||||||
use interpreter::variable::VariableInstance;
|
use interpreter::variable::{VariableType, VariableInstance};
|
||||||
|
|
||||||
|
const MEMORY_INDEX: u32 = 0;
|
||||||
const MEMORY_LIMIT_MIN: u32 = 1;
|
const MEMORY_LIMIT_MIN: u32 = 1;
|
||||||
|
|
||||||
|
const STACKTOP_INDEX: u32 = 0;
|
||||||
|
const STACKTOP_DEFAULT: i32 = 0;
|
||||||
|
const TABLE_BASE_INDEX: u32 = 0;
|
||||||
|
const TABLE_BASE_DEFAULT: i32 = 0;
|
||||||
|
|
||||||
|
const INVOKE_VI_INDEX: u32 = 0; // (i32, i32) -> ()
|
||||||
|
const INVOKE_INDEX: u32 = 1; // (i32) -> ()
|
||||||
|
|
||||||
|
const TABLE_SIZE: u32 = 1024;
|
||||||
|
const TABLE_INDEX: u32 = 0;
|
||||||
|
|
||||||
pub struct EnvModuleInstance {
|
pub struct EnvModuleInstance {
|
||||||
module: Module,
|
module: Module,
|
||||||
memory: Arc<MemoryInstance>,
|
memory: Arc<MemoryInstance>,
|
||||||
|
stacktop: Arc<VariableInstance>,
|
||||||
|
table: Arc<TableInstance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnvModuleInstance {
|
impl EnvModuleInstance {
|
||||||
@ -20,6 +35,8 @@ impl EnvModuleInstance {
|
|||||||
Ok(EnvModuleInstance {
|
Ok(EnvModuleInstance {
|
||||||
module: module,
|
module: module,
|
||||||
memory: MemoryInstance::new(&MemoryType::new(MEMORY_LIMIT_MIN, None))?,
|
memory: MemoryInstance::new(&MemoryType::new(MEMORY_LIMIT_MIN, None))?,
|
||||||
|
stacktop: Arc::new(VariableInstance::new(true, VariableType::I32, RuntimeValue::I32(STACKTOP_DEFAULT))?),
|
||||||
|
table: TableInstance::new(VariableType::AnyFunc, &TableType::new(TABLE_SIZE, None))?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,7 +46,11 @@ impl ModuleInstanceInterface for EnvModuleInstance {
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&self, _index: u32, _args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error> {
|
fn execute_index(&self, _index: u32, _args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute_export(&self, _name: &str, _args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,19 +58,25 @@ impl ModuleInstanceInterface for EnvModuleInstance {
|
|||||||
&self.module
|
&self.module
|
||||||
}
|
}
|
||||||
|
|
||||||
fn table(&self, _index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
|
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
|
||||||
unimplemented!()
|
match &index {
|
||||||
|
&ItemIndex::Internal(TABLE_INDEX) => Ok(self.table.clone()),
|
||||||
|
_ => Err(Error::Env(format!("trying to get table with index {:?} from env module", index))),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
|
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
|
||||||
match &index {
|
match &index {
|
||||||
&ItemIndex::Internal(0) => Ok(self.memory.clone()),
|
&ItemIndex::Internal(MEMORY_INDEX) => Ok(self.memory.clone()),
|
||||||
_ => Err(Error::Env(format!("trying to get memory with index {:?}", index))),
|
_ => Err(Error::Env(format!("trying to get memory with index {:?} from env module", index))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn global(&self, _index: ItemIndex) -> Result<Arc<VariableInstance>, Error> {
|
fn global(&self, index: ItemIndex) -> Result<Arc<VariableInstance>, Error> {
|
||||||
unimplemented!()
|
match &index {
|
||||||
|
&ItemIndex::Internal(STACKTOP_INDEX) => Ok(self.stacktop.clone()),
|
||||||
|
_ => Err(Error::Env(format!("trying to get global with index {:?} from env module", index))),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_function(&self, _outer: CallerContext, _index: ItemIndex) -> Result<Option<RuntimeValue>, Error> {
|
fn call_function(&self, _outer: CallerContext, _index: ItemIndex) -> Result<Option<RuntimeValue>, Error> {
|
||||||
@ -67,10 +94,39 @@ impl ModuleInstanceInterface for EnvModuleInstance {
|
|||||||
|
|
||||||
pub fn env_module() -> Result<EnvModuleInstance, Error> {
|
pub fn env_module() -> Result<EnvModuleInstance, Error> {
|
||||||
let module = module()
|
let module = module()
|
||||||
.memory()
|
// memory regions
|
||||||
.with_min(MEMORY_LIMIT_MIN)
|
.memory().with_min(MEMORY_LIMIT_MIN).build()
|
||||||
.build()
|
.with_export(ExportEntry::new("memory".into(), Internal::Memory(MEMORY_INDEX)))
|
||||||
.with_export(ExportEntry::new("memory".into(), Internal::Memory(0)))
|
// tables
|
||||||
|
.table().with_min(TABLE_SIZE).build()
|
||||||
|
.with_export(ExportEntry::new("table".into(), Internal::Table(TABLE_INDEX)))
|
||||||
|
// globals
|
||||||
|
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, true), InitExpr::new(vec![Opcode::I32Const(STACKTOP_DEFAULT)])))
|
||||||
|
.with_export(ExportEntry::new("STACKTOP".into(), Internal::Global(STACKTOP_INDEX)))
|
||||||
|
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(TABLE_BASE_DEFAULT)])))
|
||||||
|
.with_export(ExportEntry::new("tableBase".into(), Internal::Global(TABLE_BASE_INDEX)))
|
||||||
|
// functions
|
||||||
|
.with_export(ExportEntry::new("invoke_vi".into(), Internal::Function(INVOKE_VI_INDEX)))
|
||||||
|
.with_export(ExportEntry::new("invoke".into(), Internal::Function(INVOKE_INDEX)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
EnvModuleInstance::new(module)
|
EnvModuleInstance::new(module)
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
(import "env" "STACKTOP" (global (;0;) i32))
|
||||||
|
(import "env" "invoke_vi" (func (;0;) (type 3)))
|
||||||
|
(import "env" "invoke_v" (func (;1;) (type 1)))
|
||||||
|
(import "env" "_storage_size" (func (;2;) (type 2)))
|
||||||
|
(import "env" "_storage_write" (func (;3;) (type 4)))
|
||||||
|
(import "env" "_abort" (func (;4;) (type 0)))
|
||||||
|
(import "env" "_emscripten_memcpy_big" (func (;5;) (type 4)))
|
||||||
|
(import "env" "___resumeException" (func (;6;) (type 1)))
|
||||||
|
(import "env" "___cxa_find_matching_catch_2" (func (;7;) (type 2)))
|
||||||
|
(import "env" "___gxx_personality_v0" (func (;8;) (type 6)))
|
||||||
|
(import "env" "memory" (memory (;0;) 256 256))
|
||||||
|
(import "env" "table" (table (;0;) 6 6 anyfunc))
|
||||||
|
(import "env" "tableBase" (global (;1;) i32))
|
||||||
|
(import "env" "gas" (func (;9;) (type 10)))
|
||||||
|
(import "env" "_free" (func (;10;) (type 1)))
|
||||||
|
(import "env" "_malloc" (func (;11;) (type 7)))
|
||||||
|
*/
|
@ -54,7 +54,7 @@ impl ModuleImports {
|
|||||||
match index {
|
match index {
|
||||||
ItemIndex::IndexSpace(index) => match index.checked_sub(self.functions.len() as u32) {
|
ItemIndex::IndexSpace(index) => match index.checked_sub(self.functions.len() as u32) {
|
||||||
Some(index) => ItemIndex::Internal(index),
|
Some(index) => ItemIndex::Internal(index),
|
||||||
None => ItemIndex::External(index),
|
None => ItemIndex::External(self.functions[index as usize] as u32),
|
||||||
},
|
},
|
||||||
index @ _ => index,
|
index @ _ => index,
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ impl ModuleImports {
|
|||||||
match index {
|
match index {
|
||||||
ItemIndex::IndexSpace(index) => match index.checked_sub(self.tables.len() as u32) {
|
ItemIndex::IndexSpace(index) => match index.checked_sub(self.tables.len() as u32) {
|
||||||
Some(index) => ItemIndex::Internal(index),
|
Some(index) => ItemIndex::Internal(index),
|
||||||
None => ItemIndex::External(index),
|
None => ItemIndex::External(self.tables[index as usize] as u32),
|
||||||
},
|
},
|
||||||
index @ _ => index,
|
index @ _ => index,
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ impl ModuleImports {
|
|||||||
match index {
|
match index {
|
||||||
ItemIndex::IndexSpace(index) => match index.checked_sub(self.memory.len() as u32) {
|
ItemIndex::IndexSpace(index) => match index.checked_sub(self.memory.len() as u32) {
|
||||||
Some(index) => ItemIndex::Internal(index),
|
Some(index) => ItemIndex::Internal(index),
|
||||||
None => ItemIndex::External(index),
|
None => ItemIndex::External(self.memory[index as usize] as u32),
|
||||||
},
|
},
|
||||||
index @ _ => index,
|
index @ _ => index,
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ impl ModuleImports {
|
|||||||
match index {
|
match index {
|
||||||
ItemIndex::IndexSpace(index) => match index.checked_sub(self.globals.len() as u32) {
|
ItemIndex::IndexSpace(index) => match index.checked_sub(self.globals.len() as u32) {
|
||||||
Some(index) => ItemIndex::Internal(index),
|
Some(index) => ItemIndex::Internal(index),
|
||||||
None => ItemIndex::External(index),
|
None => ItemIndex::External(self.globals[index as usize] as u32),
|
||||||
},
|
},
|
||||||
index @ _ => index,
|
index @ _ => index,
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use elements::{Module, InitExpr, Opcode, Type, FunctionType, FuncBody};
|
use elements::{Module, InitExpr, Opcode, Type, FunctionType, FuncBody, Internal};
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
use interpreter::imports::ModuleImports;
|
use interpreter::imports::ModuleImports;
|
||||||
use interpreter::memory::MemoryInstance;
|
use interpreter::memory::MemoryInstance;
|
||||||
@ -15,7 +15,9 @@ pub trait ModuleInstanceInterface {
|
|||||||
/// Execute start function of the module.
|
/// Execute start function of the module.
|
||||||
fn execute_main(&self, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error>;
|
fn execute_main(&self, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error>;
|
||||||
/// Execute function with the given index.
|
/// Execute function with the given index.
|
||||||
fn execute(&self, index: u32, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error>;
|
fn execute_index(&self, index: u32, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error>;
|
||||||
|
/// Execute function with the given export name.
|
||||||
|
fn execute_export(&self, name: &str, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error>;
|
||||||
/// Get module description reference.
|
/// Get module description reference.
|
||||||
fn module(&self) -> &Module;
|
fn module(&self) -> &Module;
|
||||||
/// Get table reference.
|
/// Get table reference.
|
||||||
@ -39,7 +41,7 @@ pub enum ItemIndex {
|
|||||||
IndexSpace(u32),
|
IndexSpace(u32),
|
||||||
/// Internal item index (i.e. index of item in items section).
|
/// Internal item index (i.e. index of item in items section).
|
||||||
Internal(u32),
|
Internal(u32),
|
||||||
/// External item index (i.e. index of item in export section).
|
/// External item index (i.e. index of item in the import section).
|
||||||
External(u32),
|
External(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,16 +147,33 @@ impl ModuleInstance {
|
|||||||
impl ModuleInstanceInterface for ModuleInstance {
|
impl ModuleInstanceInterface for ModuleInstance {
|
||||||
fn execute_main(&self, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error> {
|
fn execute_main(&self, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error> {
|
||||||
let index = self.module.start_section().ok_or(Error::Program("module has no start section".into()))?;
|
let index = self.module.start_section().ok_or(Error::Program("module has no start section".into()))?;
|
||||||
self.execute(index, args)
|
self.execute_index(index, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&self, index: u32, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error> {
|
fn execute_index(&self, index: u32, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error> {
|
||||||
let args_len = args.len();
|
let args_len = args.len();
|
||||||
let mut args = StackWithLimit::with_data(args, args_len);
|
let mut args = StackWithLimit::with_data(args, args_len);
|
||||||
let caller_context = CallerContext::topmost(&mut args);
|
let caller_context = CallerContext::topmost(&mut args);
|
||||||
self.call_function(caller_context, ItemIndex::IndexSpace(index))
|
self.call_function(caller_context, ItemIndex::IndexSpace(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn execute_export(&self, name: &str, args: Vec<RuntimeValue>) -> Result<Option<RuntimeValue>, Error> {
|
||||||
|
let index = self.module.export_section()
|
||||||
|
.ok_or(Error::Function("missing export section".into()))
|
||||||
|
.and_then(|s| s.entries().iter()
|
||||||
|
.find(|e| e.field() == name && match e.internal() {
|
||||||
|
&Internal::Function(_) => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.ok_or(Error::Function(format!("missing export section exported function with name {}", name)))
|
||||||
|
.map(|e| match e.internal() {
|
||||||
|
&Internal::Function(index) => index,
|
||||||
|
_ => unreachable!(), // checked couple of lines above
|
||||||
|
})
|
||||||
|
)?;
|
||||||
|
self.execute_index(index, args)
|
||||||
|
}
|
||||||
|
|
||||||
fn module(&self) -> &Module {
|
fn module(&self) -> &Module {
|
||||||
&self.module
|
&self.module
|
||||||
}
|
}
|
||||||
@ -333,12 +352,18 @@ fn prepare_function_locals(function_type: &FunctionType, function_body: &FuncBod
|
|||||||
fn get_initializer(expr: &InitExpr, module: &Module, imports: &ModuleImports) -> Result<RuntimeValue, Error> {
|
fn get_initializer(expr: &InitExpr, module: &Module, imports: &ModuleImports) -> Result<RuntimeValue, Error> {
|
||||||
let first_opcode = expr.code().get(0).ok_or(Error::Initialization(format!("empty instantiation-time initializer")))?;
|
let first_opcode = expr.code().get(0).ok_or(Error::Initialization(format!("empty instantiation-time initializer")))?;
|
||||||
match first_opcode {
|
match first_opcode {
|
||||||
&Opcode::GetGlobal(index) => module.import_section()
|
&Opcode::GetGlobal(index) => {
|
||||||
.ok_or(Error::Global(format!("trying to initialize with external global with index {} in module without import section", index)))
|
let index = match imports.parse_global_index(ItemIndex::IndexSpace(index)) {
|
||||||
.and_then(|s| s.entries().get(index as usize)
|
ItemIndex::External(index) => index,
|
||||||
.ok_or(Error::Global(format!("trying to initialize with external global with index {} in module with {}-entries import section", index, s.entries().len()))))
|
_ => return Err(Error::Global(format!("trying to initialize with non-external global {}", index))),
|
||||||
.and_then(|e| imports.global(e))
|
};
|
||||||
.map(|g| g.get()),
|
module.import_section()
|
||||||
|
.ok_or(Error::Global(format!("trying to initialize with external global with index {} in module without import section", index)))
|
||||||
|
.and_then(|s| s.entries().get(index as usize)
|
||||||
|
.ok_or(Error::Global(format!("trying to initialize with external global with index {} in module with {}-entries import section", index, s.entries().len()))))
|
||||||
|
.and_then(|e| imports.global(e))
|
||||||
|
.map(|g| g.get())
|
||||||
|
},
|
||||||
&Opcode::I32Const(val) => Ok(RuntimeValue::I32(val)),
|
&Opcode::I32Const(val) => Ok(RuntimeValue::I32(val)),
|
||||||
&Opcode::I64Const(val) => Ok(RuntimeValue::I64(val)),
|
&Opcode::I64Const(val) => Ok(RuntimeValue::I64(val)),
|
||||||
&Opcode::F32Const(val) => Ok(RuntimeValue::F32(val.transmute_into())),
|
&Opcode::F32Const(val) => Ok(RuntimeValue::F32(val.transmute_into())),
|
||||||
|
@ -280,13 +280,11 @@ macro_rules! impl_try_truncate_into {
|
|||||||
impl TryTruncateInto<$into, Error> for $from {
|
impl TryTruncateInto<$into, Error> for $from {
|
||||||
fn try_truncate_into(self) -> Result<$into, Error> {
|
fn try_truncate_into(self) -> Result<$into, Error> {
|
||||||
if !self.is_normal() {
|
if !self.is_normal() {
|
||||||
println!("=== !IS_NORMAL: {}", self);
|
|
||||||
return Err(Error::Value("invalid float value for this operation".into()));
|
return Err(Error::Value("invalid float value for this operation".into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let truncated = self.trunc();
|
let truncated = self.trunc();
|
||||||
if truncated < $into::MIN as $from || truncated > $into::MAX as $from {
|
if truncated < $into::MIN as $from || truncated > $into::MAX as $from {
|
||||||
println!("=== {} < {} || {} > {}", truncated, $into::MIN, truncated, $into::MIN);
|
|
||||||
return Err(Error::Value("invalid float value for this operation".into()));
|
return Err(Error::Value("invalid float value for this operation".into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user