Operator::Br and control stack fixes

This commit is contained in:
losfair 2019-02-20 23:21:33 +08:00
parent 61c83507a4
commit aaabbf169c

View File

@ -79,7 +79,6 @@ pub struct X64FunctionCode {
id: usize, id: usize,
begin_label: DynamicLabel, begin_label: DynamicLabel,
begin_offset: AssemblyOffset, begin_offset: AssemblyOffset,
cleanup_label: DynamicLabel,
assembler: Option<Assembler>, assembler: Option<Assembler>,
returns: Vec<WpType>, returns: Vec<WpType>,
locals: Vec<Local>, locals: Vec<Local>,
@ -170,13 +169,12 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext> for X64ModuleCode
; => begin_label ; => begin_label
; push rbp ; push rbp
; mov rbp, rsp ; mov rbp, rsp
//; int 3 ; int 3
); );
let code = X64FunctionCode { let code = X64FunctionCode {
id: self.functions.len(), id: self.functions.len(),
begin_label: begin_label, begin_label: begin_label,
begin_offset: begin_offset, begin_offset: begin_offset,
cleanup_label: assembler.new_dynamic_label(),
assembler: Some(assembler), assembler: Some(assembler),
returns: vec![], returns: vec![],
locals: vec![], locals: vec![],
@ -351,6 +349,39 @@ impl X64FunctionCode {
} }
} }
fn emit_pop_into_ax(
assembler: &mut Assembler,
value_stack: &mut ValueStack,
) -> Result<(), CodegenError> {
let val = value_stack.pop()?;
match val.location {
ValueLocation::Register(x) => {
let reg = Register::from_scratch_reg(x);
dynasm!(
assembler
; mov rax, Rq(reg as u8)
);
}
ValueLocation::Stack => {
if is_dword(get_size_of_type(&val.ty)?) {
dynasm!(
assembler
; mov eax, [rsp]
; add rsp, 4
);
} else {
dynasm!(
assembler
; mov rax, [rsp]
; add rsp, 8
);
}
}
}
Ok(())
}
fn emit_leave_frame( fn emit_leave_frame(
assembler: &mut Assembler, assembler: &mut Assembler,
frame: &ControlFrame, frame: &ControlFrame,
@ -379,30 +410,12 @@ impl X64FunctionCode {
} }
if let Some(ty) = ret_ty { if let Some(ty) = ret_ty {
let ret = value_stack.pop()?; if value_stack.values.iter().last().map(|x| x.ty) != ret_ty {
match ret.location { return Err(CodegenError {
ValueLocation::Register(x) => { message: "value type != return type",
dynasm!( });
assembler
; mov rax, Rq(x)
);
}
ValueLocation::Stack => {
if is_dword(get_size_of_type(&ty)?) {
dynasm!(
assembler
; mov eax, [rsp]
; add rsp, 4
);
} else {
dynasm!(
assembler
; mov rax, [rsp]
; add rsp, 8
);
}
}
} }
Self::emit_pop_into_ax(assembler, value_stack)?;
} }
Ok(()) Ok(())
@ -741,22 +754,19 @@ impl FunctionCodeGenerator for X64FunctionCode {
Operator::Return => match self.returns.len() { Operator::Return => match self.returns.len() {
0 => {} 0 => {}
1 => { 1 => {
let val = self.value_stack.pop()?; if self.value_stack.values.iter().last().map(|x| x.ty) != Some(self.returns[0])
let ty = self.returns[0]; {
let reg = val.location.get_register()?; return Err(CodegenError {
if is_dword(get_size_of_type(&ty)?) { message: "self.value_stack.last().cloned() != Some(self.returns[0])",
dynasm!( });
assembler
; mov eax, Rd(Register::from_scratch_reg(reg) as u8)
; jmp =>self.cleanup_label
);
} else {
dynasm!(
assembler
; mov rax, Rq(Register::from_scratch_reg(reg) as u8)
; jmp =>self.cleanup_label
);
} }
Self::emit_pop_into_ax(assembler, &mut self.value_stack)?;
dynasm!(
assembler
; mov rsp, rbp
; pop rbp
; ret
);
} }
_ => { _ => {
return Err(CodegenError { return Err(CodegenError {
@ -771,6 +781,14 @@ impl FunctionCodeGenerator for X64FunctionCode {
&mut self.value_stack, &mut self.value_stack,
)?; )?;
} }
Operator::Br { relative_depth } => {
Self::emit_jmp(
assembler,
self.control_stack.as_ref().unwrap(),
&mut self.value_stack,
relative_depth as usize,
)?;
}
_ => unimplemented!(), _ => unimplemented!(),
} }
Ok(()) Ok(())
@ -782,38 +800,15 @@ impl FunctionCodeGenerator for X64FunctionCode {
dynasm!( dynasm!(
assembler assembler
; ud2 ; ud2
; => self.cleanup_label
); );
if self.returns.len() == 1 { if self.value_stack.values.len() != 0
if self.value_stack.values.len() != 1 { || self.control_stack.as_ref().unwrap().frames.len() != 0
{
return Err(CodegenError { return Err(CodegenError {
message: "returns.len() != value_stack.values.len()", message: "control/value stack not empty at end of function",
}); });
} }
let value_info = self.value_stack.pop()?;
if value_info.ty != self.returns[0] {
return Err(CodegenError {
message: "return type mismatch",
});
}
if let ValueLocation::Register(x) = value_info.location {
let reg = Register::from_scratch_reg(x);
dynasm!(
assembler
; mov rax, Rq(reg as u8)
);
} else {
unreachable!();
}
}
dynasm!(
assembler
; mov rsp, rbp
; pop rbp
; ret
);
Ok(()) Ok(())
} }