mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 14:25:32 +00:00
If/Else.
This commit is contained in:
parent
3c3c5db2e1
commit
d50f1cc95f
@ -1,5 +1,5 @@
|
|||||||
use super::codegen::*;
|
use super::codegen::*;
|
||||||
use super::stack::{ControlFrame, ControlStack, ValueInfo, ValueLocation, ValueStack};
|
use super::stack::{ControlFrame, ControlStack, IfElseState, ValueInfo, ValueLocation, ValueStack};
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
use dynasmrt::{
|
use dynasmrt::{
|
||||||
x64::Assembler, AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, ExecutableBuffer,
|
x64::Assembler, AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, ExecutableBuffer,
|
||||||
@ -670,6 +670,52 @@ impl X64FunctionCode {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_else(
|
||||||
|
assembler: &mut Assembler,
|
||||||
|
control_stack: &mut ControlStack,
|
||||||
|
value_stack: &mut ValueStack,
|
||||||
|
was_unreachable: bool,
|
||||||
|
) -> Result<(), CodegenError> {
|
||||||
|
let frame = match control_stack.frames.last_mut() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => {
|
||||||
|
return Err(CodegenError {
|
||||||
|
message: "no frame",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if !was_unreachable {
|
||||||
|
Self::emit_leave_frame(assembler, frame, value_stack, false)?;
|
||||||
|
if value_stack.values.len() != frame.value_stack_depth_before {
|
||||||
|
return Err(CodegenError {
|
||||||
|
message: "value_stack.values.len() != frame.value_stack_depth_before",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No need to actually unwind the stack here.
|
||||||
|
value_stack.reset_depth(frame.value_stack_depth_before);
|
||||||
|
}
|
||||||
|
|
||||||
|
match frame.if_else {
|
||||||
|
IfElseState::If(label) => {
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; jmp =>frame.label
|
||||||
|
; => label
|
||||||
|
);
|
||||||
|
frame.if_else = IfElseState::Else;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(CodegenError {
|
||||||
|
message: "unexpected if else state",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_block_end(
|
fn emit_block_end(
|
||||||
assembler: &mut Assembler,
|
assembler: &mut Assembler,
|
||||||
control_stack: &mut ControlStack,
|
control_stack: &mut ControlStack,
|
||||||
@ -698,11 +744,28 @@ impl X64FunctionCode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !frame.loop_like {
|
if !frame.loop_like {
|
||||||
|
match frame.if_else {
|
||||||
|
IfElseState::None | IfElseState::Else => {
|
||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; => frame.label
|
; => frame.label
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
IfElseState::If(label) => {
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; => frame.label
|
||||||
|
; => label
|
||||||
|
);
|
||||||
|
|
||||||
|
if frame.returns.len() != 0 {
|
||||||
|
return Err(CodegenError {
|
||||||
|
message: "if without else, with non-empty returns",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if frame.returns.len() == 1 {
|
if frame.returns.len() == 1 {
|
||||||
let loc = value_stack.push(frame.returns[0]);
|
let loc = value_stack.push(frame.returns[0]);
|
||||||
@ -1434,6 +1497,7 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
.push(ControlFrame {
|
.push(ControlFrame {
|
||||||
label: assembler.new_dynamic_label(),
|
label: assembler.new_dynamic_label(),
|
||||||
loop_like: false,
|
loop_like: false,
|
||||||
|
if_else: IfElseState::None,
|
||||||
returns: match ty {
|
returns: match ty {
|
||||||
WpType::EmptyBlockType => vec![],
|
WpType::EmptyBlockType => vec![],
|
||||||
_ => vec![ty],
|
_ => vec![ty],
|
||||||
@ -1525,6 +1589,7 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
.push(ControlFrame {
|
.push(ControlFrame {
|
||||||
label: label,
|
label: label,
|
||||||
loop_like: true,
|
loop_like: true,
|
||||||
|
if_else: IfElseState::None,
|
||||||
returns: match ty {
|
returns: match ty {
|
||||||
WpType::EmptyBlockType => vec![],
|
WpType::EmptyBlockType => vec![],
|
||||||
_ => vec![ty],
|
_ => vec![ty],
|
||||||
@ -1536,6 +1601,40 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
; =>label
|
; =>label
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Operator::If { ty } => {
|
||||||
|
let label_end = assembler.new_dynamic_label();
|
||||||
|
let label_else = assembler.new_dynamic_label();
|
||||||
|
|
||||||
|
Self::emit_pop_into_ax(assembler, &mut self.value_stack)?; // TODO: typeck?
|
||||||
|
|
||||||
|
self.control_stack
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.frames
|
||||||
|
.push(ControlFrame {
|
||||||
|
label: label_end,
|
||||||
|
loop_like: false,
|
||||||
|
if_else: IfElseState::If(label_else),
|
||||||
|
returns: match ty {
|
||||||
|
WpType::EmptyBlockType => vec![],
|
||||||
|
_ => vec![ty],
|
||||||
|
},
|
||||||
|
value_stack_depth_before: self.value_stack.values.len(),
|
||||||
|
});
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; cmp eax, 0
|
||||||
|
; je =>label_else
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Operator::Else => {
|
||||||
|
Self::emit_else(
|
||||||
|
assembler,
|
||||||
|
self.control_stack.as_mut().unwrap(),
|
||||||
|
&mut self.value_stack,
|
||||||
|
was_unreachable,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
Operator::Br { relative_depth } => {
|
Operator::Br { relative_depth } => {
|
||||||
Self::emit_jmp(
|
Self::emit_jmp(
|
||||||
assembler,
|
assembler,
|
||||||
|
@ -21,10 +21,18 @@ pub enum RegisterName {
|
|||||||
Invalid,
|
Invalid,
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum IfElseState {
|
||||||
|
None,
|
||||||
|
If(DynamicLabel),
|
||||||
|
Else,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ControlFrame {
|
pub struct ControlFrame {
|
||||||
pub label: DynamicLabel,
|
pub label: DynamicLabel,
|
||||||
pub loop_like: bool,
|
pub loop_like: bool,
|
||||||
|
pub if_else: IfElseState,
|
||||||
pub returns: Vec<WpType>,
|
pub returns: Vec<WpType>,
|
||||||
pub value_stack_depth_before: usize,
|
pub value_stack_depth_before: usize,
|
||||||
}
|
}
|
||||||
@ -147,6 +155,7 @@ impl ControlStack {
|
|||||||
frames: vec![ControlFrame {
|
frames: vec![ControlFrame {
|
||||||
label: label,
|
label: label,
|
||||||
loop_like: false,
|
loop_like: false,
|
||||||
|
if_else: IfElseState::None,
|
||||||
returns: returns,
|
returns: returns,
|
||||||
value_stack_depth_before: 0,
|
value_stack_depth_before: 0,
|
||||||
}],
|
}],
|
||||||
|
Loading…
Reference in New Issue
Block a user