This commit is contained in:
vms 2020-09-15 19:58:35 +03:00
parent 2a756bd485
commit f2f0792820
10 changed files with 75 additions and 77 deletions

View File

@ -123,9 +123,9 @@ fn ty<'input, E: ParseError<&'input [u8]>>(
0x0c => InterfaceType::I32,
0x0d => InterfaceType::I64,
0x0e => {
consume!((input, record_name) = owned_string(input)?);
consume!((input, record_id) = uleb(input)?);
InterfaceType::Record(record_name)
InterfaceType::Record(record_id)
}
_ => return Err(Err::Error(make_error(input, ErrorKind::ParseTo))),
};
@ -320,7 +320,7 @@ fn instruction<'input, E: ParseError<&'input [u8]>>(
(
input,
Instruction::RecordLiftMemory {
type_index: argument_0 as u32,
record_type_id: argument_0 as u32,
},
)
}
@ -330,7 +330,7 @@ fn instruction<'input, E: ParseError<&'input [u8]>>(
(
input,
Instruction::RecordLowerMemory {
type_index: argument_0 as u32,
record_type_id: argument_0 as u32,
},
)
}

View File

@ -368,13 +368,13 @@ impl<'a> Parse<'a> for Instruction {
parser.parse::<keyword::record_lift_memory>()?;
Ok(Instruction::RecordLiftMemory {
type_index: parser.parse()?,
record_type_id: parser.parse()?,
})
} else if lookahead.peek::<keyword::record_lower_memory>() {
parser.parse::<keyword::record_lower_memory>()?;
Ok(Instruction::RecordLowerMemory {
type_index: parser.parse()?,
record_type_id: parser.parse()?,
})
} else if lookahead.peek::<keyword::dup>() {
parser.parse::<keyword::dup>()?;

View File

@ -127,9 +127,9 @@ where
InterfaceType::Anyref => 0x0b_u8.to_bytes(writer),
InterfaceType::I32 => 0x0c_u8.to_bytes(writer),
InterfaceType::I64 => 0x0d_u8.to_bytes(writer),
InterfaceType::Record(record_type) => {
InterfaceType::Record(record_id) => {
0x0e_u8.to_bytes(writer)?;
record_type.as_str().to_bytes(writer)
record_id.to_bytes(writer)
}
}
}
@ -391,11 +391,15 @@ where
(*type_index as u64).to_bytes(writer)?
}
*/
Instruction::RecordLiftMemory { type_index } => {
Instruction::RecordLiftMemory {
record_type_id: type_index,
} => {
0x3A_u8.to_bytes(writer)?;
(*type_index as u64).to_bytes(writer)?
}
Instruction::RecordLowerMemory { type_index } => {
Instruction::RecordLowerMemory {
record_type_id: type_index,
} => {
0x3B_u8.to_bytes(writer)?;
(*type_index as u64).to_bytes(writer)?
}

View File

@ -151,12 +151,12 @@ impl ToString for &Instruction {
Instruction::RecordLift { type_index } => format!("record.lift {}", type_index),
Instruction::RecordLower { type_index } => format!("record.lower {}", type_index),
*/
Instruction::RecordLiftMemory { type_index } => {
format!("record.lift_memory {}", type_index)
}
Instruction::RecordLowerMemory { type_index } => {
format!("record.lower_memory {}", type_index)
}
Instruction::RecordLiftMemory {
record_type_id: type_index,
} => format!("record.lift_memory {}", type_index),
Instruction::RecordLowerMemory {
record_type_id: type_index,
} => format!("record.lower_memory {}", type_index),
Instruction::Dup => "dup".into(),
Instruction::Swap2 => "swap2".into(),
}

View File

@ -167,7 +167,7 @@ pub enum InstructionErrorKind {
/// The searched by name type doesn't exist.
RecordTypeByNameIsMissing {
/// The record type name.
type_name: String,
record_type_id: u64,
},
/// Corrupted record's been popped from the stack.
@ -272,7 +272,7 @@ impl Display for InstructionErrorKind {
received_kind, expected_kind
),
Self::RecordTypeByNameIsMissing { type_name } => write!(
Self::RecordTypeByNameIsMissing { record_type_id: type_name } => write!(
formatter,
"type with `{}` is missing in a Wasm binary",
type_name

View File

@ -8,7 +8,7 @@ mod strings;
mod swap2;
use crate::interpreter::wasm;
use crate::types::{InterfaceType, RecordType};
use crate::types::InterfaceType;
use crate::vec1::Vec1;
use crate::{
errors::{InstructionError, InstructionErrorKind, InstructionResult, WasmValueNativeCastError},
@ -173,13 +173,13 @@ pub enum Instruction {
/// The `record.lift_memory` instruction.
RecordLiftMemory {
/// The type index of the record.
type_index: u32,
record_type_id: u32,
},
/// The `record.lower_memory` instruction.
RecordLowerMemory {
/// The type index of the record.
type_index: u32,
record_type_id: u32,
},
/// The `dup` instructions.
@ -267,17 +267,13 @@ where
(InterfaceType::F64, InterfaceValue::F64(_)) => Ok(()),
(InterfaceType::String, InterfaceValue::String(_)) => Ok(()),
(InterfaceType::ByteArray, InterfaceValue::ByteArray(_)) => Ok(()),
(InterfaceType::Record(ref record_name), InterfaceValue::Record(record_fields)) => {
let record_type = instance.wit_record_by_name(record_name).ok_or_else(|| {
InstructionError::new(
instruction,
InstructionErrorKind::RecordTypeByNameIsMissing {
type_name: record_name.to_owned(),
},
)
})?;
is_record_fields_compatible_to_type(instance, record_type, record_fields, instruction)?;
(InterfaceType::Record(ref record_type_id), InterfaceValue::Record(record_fields)) => {
is_record_fields_compatible_to_type(
instance,
*record_type_id,
record_fields,
instruction,
)?;
Ok(())
}
@ -300,7 +296,7 @@ pub(crate) fn is_record_fields_compatible_to_type<
MemoryView,
>(
instance: &'instance Instance,
record_type: &RecordType,
record_type_id: u64,
record_fields: &[InterfaceValue],
instruction: Instruction,
) -> Result<(), InstructionError>
@ -311,18 +307,18 @@ where
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
if record_fields.is_empty() {
return Err(InstructionError::new(
let record_type = instance.wit_record_by_id(record_type_id).ok_or_else(|| {
InstructionError::new(
instruction,
InstructionErrorKind::CorruptedRecord(String::from("record contains no fields")),
));
}
InstructionErrorKind::RecordTypeByNameIsMissing { record_type_id },
)
})?;
if record_fields.len() != record_type.fields.len() {
return Err(InstructionError::new(
instruction,
InstructionErrorKind::InvalidValueOnTheStack {
expected_type: InterfaceType::Record(record_type.name.clone()),
expected_type: InterfaceType::Record(record_type_id),
// unwrap is safe here - len's been already checked
received_value: InterfaceValue::Record(Vec1::new(record_fields.to_vec()).unwrap()),
},

View File

@ -216,20 +216,17 @@ where
values.push_back(InterfaceValue::ByteArray(vec![]));
}
}
InterfaceType::Record(record_type_name) => {
InterfaceType::Record(record_type_id) => {
let offset = value;
let record_type =
instance
.wit_record_by_name(&record_type_name)
.ok_or_else(|| {
InstructionError::new(
instruction,
InstructionErrorKind::RecordTypeByNameIsMissing {
type_name: record_type_name.to_owned(),
},
)
})?;
let record_type = instance.wit_record_by_id(*record_type_id).ok_or_else(|| {
InstructionError::new(
instruction,
InstructionErrorKind::RecordTypeByNameIsMissing {
record_type_id: *record_type_id,
},
)
})?;
values.push_back(record_lift_memory_(
instance,
@ -251,7 +248,7 @@ where
}
pub(crate) fn record_lift_memory<Instance, Export, LocalImport, Memory, MemoryView>(
type_index: u32,
record_type_id: u64,
instruction: Instruction,
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
where
@ -280,10 +277,10 @@ where
// TODO: size = 0
let instance = &runtime.wasm_instance;
let record_type = instance.wit_record_by_id(type_index).ok_or_else(|| {
let record_type = instance.wit_record_by_id(record_type_id).ok_or_else(|| {
InstructionError::new(
instruction,
InstructionErrorKind::TypeIsMissing { type_index },
InstructionErrorKind::RecordTypeByNameIsMissing { record_type_id },
)
})?;
@ -364,7 +361,7 @@ where
}
pub(crate) fn record_lower_memory<Instance, Export, LocalImport, Memory, MemoryView>(
type_index: u32,
record_type_id: u64,
instruction: Instruction,
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
where
@ -380,18 +377,12 @@ where
Box::new({
move |runtime| -> _ {
let instance = &mut runtime.wasm_instance;
let record_type = instance.wit_record_by_id(type_index).ok_or_else(|| {
InstructionError::new(
instruction,
InstructionErrorKind::TypeIsMissing { type_index },
)
})?;
match runtime.stack.pop1() {
Some(InterfaceValue::Record(record_fields)) => {
is_record_fields_compatible_to_type(
&**instance,
record_type,
record_type_id,
&record_fields,
instruction,
)?;
@ -403,7 +394,7 @@ where
Some(value) => Err(InstructionError::new(
instruction,
InstructionErrorKind::InvalidValueOnTheStack {
expected_type: InterfaceType::Record(record_type.name.clone()),
expected_type: InterfaceType::Record(record_type_id),
received_value: value,
},
)),

View File

@ -253,11 +253,11 @@ where
instructions::record_lower(*type_index, *instruction)
}
*/
Instruction::RecordLiftMemory { type_index } => {
instructions::record_lift_memory(*type_index, *instruction)
Instruction::RecordLiftMemory { record_type_id } => {
instructions::record_lift_memory(*record_type_id as _, *instruction)
}
Instruction::RecordLowerMemory { type_index } => {
instructions::record_lower_memory(*type_index, *instruction)
Instruction::RecordLowerMemory { record_type_id } => {
instructions::record_lower_memory(*record_type_id as _, *instruction)
}
Instruction::Dup => instructions::dup(*instruction),
Instruction::Swap2 => instructions::swap2(*instruction),

View File

@ -76,8 +76,7 @@ where
fn export(&self, export_name: &str) -> Option<&E>;
fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&LI>;
fn memory(&self, index: usize) -> Option<&M>;
fn wit_record_by_id(&self, index: u32) -> Option<&RecordType>;
fn wit_record_by_name(&self, name: &str) -> Option<&RecordType>;
fn wit_record_by_id(&self, index: u64) -> Option<&RecordType>;
}
impl Export for () {
@ -161,11 +160,7 @@ where
None
}
fn wit_record_by_id(&self, _index: u32) -> Option<&RecordType> {
None
}
fn wit_record_by_name(&self, _name: &str) -> Option<&RecordType> {
fn wit_record_by_id(&self, _index: u64) -> Option<&RecordType> {
None
}
}

View File

@ -51,9 +51,8 @@ pub enum InterfaceType {
/// A 64-bits integer (as defiend in WebAssembly core).
I64,
/// A record contains type name.
// TODO: consider making it &str
Record(String),
/// A record contains record index from interfaces AST.
Record(u64),
}
/// Represents a record field type.
@ -78,3 +77,16 @@ pub struct RecordType {
/// [`Vec1`][crate::vec1::Vec1].
pub fields: Vec1<RecordFieldType>,
}
impl Default for RecordType {
fn default() -> Self {
Self {
name: String::new(),
fields: Vec1::new(vec![RecordFieldType {
name: String::new(),
ty: InterfaceType::S8,
}])
.unwrap(),
}
}
}