mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 22:25:40 +00:00
Handle unreachable and fix return.
This commit is contained in:
parent
6f97ebd5f7
commit
63b3f41f05
@ -86,6 +86,7 @@ pub struct X64FunctionCode {
|
|||||||
current_stack_offset: usize,
|
current_stack_offset: usize,
|
||||||
value_stack: ValueStack,
|
value_stack: ValueStack,
|
||||||
control_stack: Option<ControlStack>,
|
control_stack: Option<ControlStack>,
|
||||||
|
unreachable_depth: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct X64ExecutionContext {
|
pub struct X64ExecutionContext {
|
||||||
@ -182,6 +183,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext> for X64ModuleCode
|
|||||||
current_stack_offset: 0,
|
current_stack_offset: 0,
|
||||||
value_stack: ValueStack::new(4),
|
value_stack: ValueStack::new(4),
|
||||||
control_stack: None,
|
control_stack: None,
|
||||||
|
unreachable_depth: 0,
|
||||||
};
|
};
|
||||||
self.functions.push(code);
|
self.functions.push(code);
|
||||||
Ok(self.functions.last_mut().unwrap())
|
Ok(self.functions.last_mut().unwrap())
|
||||||
@ -516,6 +518,38 @@ impl X64FunctionCode {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_return(
|
||||||
|
assembler: &mut Assembler,
|
||||||
|
value_stack: &mut ValueStack,
|
||||||
|
returns: &Vec<WpType>,
|
||||||
|
) -> Result<(), CodegenError> {
|
||||||
|
match returns.len() {
|
||||||
|
0 => {}
|
||||||
|
1 => {
|
||||||
|
if value_stack.values.iter().last().map(|x| x.ty) != Some(returns[0]) {
|
||||||
|
return Err(CodegenError {
|
||||||
|
message: "self.value_stack.last().cloned() != Some(self.returns[0])",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Self::emit_pop_into_ax(assembler, value_stack)?;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(CodegenError {
|
||||||
|
message: "multiple return values is not yet supported",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; mov rsp, rbp
|
||||||
|
; pop rbp
|
||||||
|
; ret
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionCodeGenerator for X64FunctionCode {
|
impl FunctionCodeGenerator for X64FunctionCode {
|
||||||
@ -600,7 +634,28 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn feed_opcode(&mut self, op: Operator) -> Result<(), CodegenError> {
|
fn feed_opcode(&mut self, op: Operator) -> Result<(), CodegenError> {
|
||||||
|
let was_unreachable;
|
||||||
|
|
||||||
|
if self.unreachable_depth > 0 {
|
||||||
|
was_unreachable = true;
|
||||||
|
match op {
|
||||||
|
Operator::Block { .. } | Operator::Loop { .. } | Operator::If { .. } => {
|
||||||
|
self.unreachable_depth += 1;
|
||||||
|
}
|
||||||
|
Operator::End => {
|
||||||
|
self.unreachable_depth -= 1;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
if self.unreachable_depth > 0 {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
was_unreachable = false;
|
||||||
|
}
|
||||||
|
|
||||||
let assembler = self.assembler.as_mut().unwrap();
|
let assembler = self.assembler.as_mut().unwrap();
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
Operator::GetLocal { local_index } => {
|
Operator::GetLocal { local_index } => {
|
||||||
let local_index = local_index as usize;
|
let local_index = local_index as usize;
|
||||||
@ -751,36 +806,26 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
let info = self.value_stack.pop()?;
|
let info = self.value_stack.pop()?;
|
||||||
Self::gen_rt_pop(assembler, &info)?;
|
Self::gen_rt_pop(assembler, &info)?;
|
||||||
}
|
}
|
||||||
Operator::Return => match self.returns.len() {
|
Operator::Return => {
|
||||||
0 => {}
|
Self::emit_return(assembler, &mut self.value_stack, &self.returns)?;
|
||||||
1 => {
|
self.unreachable_depth = 1;
|
||||||
if self.value_stack.values.iter().last().map(|x| x.ty) != Some(self.returns[0])
|
|
||||||
{
|
|
||||||
return Err(CodegenError {
|
|
||||||
message: "self.value_stack.last().cloned() != Some(self.returns[0])",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Self::emit_pop_into_ax(assembler, &mut self.value_stack)?;
|
Operator::End => {
|
||||||
|
if self.control_stack.as_ref().unwrap().frames.len() == 1 {
|
||||||
|
let frame = self.control_stack.as_mut().unwrap().frames.pop().unwrap();
|
||||||
|
Self::emit_leave_frame(assembler, &frame, &mut self.value_stack)?;
|
||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; mov rsp, rbp
|
; =>frame.label
|
||||||
; pop rbp
|
|
||||||
; ret
|
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
_ => {
|
|
||||||
return Err(CodegenError {
|
|
||||||
message: "multiple return values is not yet supported",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Operator::End => {
|
|
||||||
Self::emit_block_end(
|
Self::emit_block_end(
|
||||||
assembler,
|
assembler,
|
||||||
self.control_stack.as_mut().unwrap(),
|
self.control_stack.as_mut().unwrap(),
|
||||||
&mut self.value_stack,
|
&mut self.value_stack,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Operator::Br { relative_depth } => {
|
Operator::Br { relative_depth } => {
|
||||||
Self::emit_jmp(
|
Self::emit_jmp(
|
||||||
assembler,
|
assembler,
|
||||||
@ -788,6 +833,7 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
&mut self.value_stack,
|
&mut self.value_stack,
|
||||||
relative_depth as usize,
|
relative_depth as usize,
|
||||||
)?;
|
)?;
|
||||||
|
self.unreachable_depth = 1;
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
@ -799,7 +845,9 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
|
|
||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; ud2
|
; mov rsp, rbp
|
||||||
|
; pop rbp
|
||||||
|
; ret
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.value_stack.values.len() != 0
|
if self.value_stack.values.len() != 0
|
||||||
|
Loading…
Reference in New Issue
Block a user