From 47c1e0389d586e641b122f3a54ce9789ee12facb Mon Sep 17 00:00:00 2001 From: Cassie Jones Date: Mon, 2 Mar 2020 16:24:00 +0100 Subject: [PATCH] Add CFI directives CFI is the "Call Frame Information", it provides instructions about where the call frame is. Since we're not emitting a frame pointer, we need some way to tell debuggers where our call frames our. These CFI directives let you provide instructions to find the beginning of the call frame. In our case, we just want to tell it what offsets from the stack pointer it needs to find it. These cause the assembler to put all of this metadata in a separate "eh" frame info section that tools can inspect, it doesn't modify the actual code. Adding these makes using the "up" and "down" commands in the debugger more reliable when looking at my emitted functions. Previously they would sometimes fail to figure out where they were, making debugging annoying. --- src/trans/x64.rs | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/trans/x64.rs b/src/trans/x64.rs index 8dc2de7..473db2a 100644 --- a/src/trans/x64.rs +++ b/src/trans/x64.rs @@ -55,9 +55,16 @@ pub enum Reg { R15, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Cfi { + Def(Reg, i32), +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Inst { Push(Reg), + Pop(Reg), + Cfi(Cfi), Load(Reg, Addr), Store(Addr, Reg), Mov(Reg, Reg), @@ -65,9 +72,8 @@ pub enum Inst { Lea(Reg, Addr), Call(Label), Jmp(Label), - Add(Reg, u32), - Sub(Reg, u32), - Pop(Reg), + AddI(Reg, u32), + SubI(Reg, u32), Ret, } @@ -199,8 +205,10 @@ fn compile_func(func: &Func) -> Definition { let mut body = Vec::new(); let stack_slots = even_up(func.order.len()); body.push(Inst::Push(Reg::Rbx)); + body.push(Inst::Cfi(Cfi::Def(Reg::Rsp, 16))); body.push(Inst::Mov(Reg::Rbx, Reg::Rdi)); - body.push(Inst::Sub(Reg::Rsp, stack_slots as u32 * 8)); + body.push(Inst::SubI(Reg::Rsp, stack_slots as u32 * 8)); + body.push(Inst::Cfi(Cfi::Def(Reg::Rsp, stack_slots as i32 * 8 + 16))); let address = |v| match v { Var::Global(x) => Addr::Rip(Label::Global(x)), Var::Param(x) => param(x), @@ -263,8 +271,10 @@ fn compile_func(func: &Func) -> Definition { Code::Num(n) => body.push(Inst::Imm(Reg::Rax, (n << 1) | 1i64)), _ => (), } - body.push(Inst::Add(Reg::Rsp, stack_slots as u32 * 8)); + body.push(Inst::AddI(Reg::Rsp, stack_slots as u32 * 8)); + body.push(Inst::Cfi(Cfi::Def(Reg::Rsp, 16))); body.push(Inst::Pop(Reg::Rbx)); + body.push(Inst::Cfi(Cfi::Def(Reg::Rsp, 8))); body.push(Inst::Ret); Definition { name: Label::Function(func.name), @@ -274,15 +284,17 @@ fn compile_func(func: &Func) -> Definition { impl fmt::Display for Definition { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + writeln!(fmt, " .globl {}", self.name)?; match self.body.len() { 0 => write!(fmt, "{}:", self.name), 1 => write!(fmt, "{}: {}", self.name, self.body[0]), - len => { + _ => { + writeln!(fmt, " .cfi_startproc")?; writeln!(fmt, "{}:", self.name)?; - for inst in &self.body[..len - 1] { + for inst in self.body.as_ref() { writeln!(fmt, " {}", inst)?; } - write!(fmt, " {}", self.body.last().unwrap()) + write!(fmt, " .cfi_endproc") } } } @@ -337,11 +349,20 @@ impl fmt::Display for Addr { } } +impl fmt::Display for Cfi { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self { + Cfi::Def(r, i) => write!(fmt, ".cfi_def_cfa {}, {}", r, i), + } + } +} + impl fmt::Display for Inst { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self { Inst::Push(r) => write!(fmt, "push {}", r), Inst::Pop(r) => write!(fmt, "pop {}", r), + Inst::Cfi(c) => write!(fmt, "{}", c), Inst::Mov(d, s) => write!(fmt, "mov {}, {}", d, s), Inst::Load(r, a) => write!(fmt, "mov {}, {}", r, a), Inst::Store(a, r) => write!(fmt, "mov {}, {}", a, r), @@ -349,8 +370,8 @@ impl fmt::Display for Inst { Inst::Lea(r, a) => write!(fmt, "lea {}, {}", r, a), Inst::Call(l) => write!(fmt, "call {}", l), Inst::Jmp(l) => write!(fmt, "jmp {}", l), - Inst::Add(r, x) => write!(fmt, "add {}, {}", r, x), - Inst::Sub(r, x) => write!(fmt, "sub {}, {}", r, x), + Inst::AddI(r, x) => write!(fmt, "add {}, {}", r, x), + Inst::SubI(r, x) => write!(fmt, "sub {}, {}", r, x), Inst::Ret => write!(fmt, "ret"), } } -- 2.43.2