Skip to content

Commit

Permalink
codegen/x86_64: Change stack size to usize & refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
mrkajetanp committed Sep 16, 2024
1 parent a70c7ae commit c41aa1c
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 46 deletions.
20 changes: 10 additions & 10 deletions src/codegen/x86_64/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fn function() {
Instruction::Mov(Operand::Reg(Register::AX), Operand::Stack(-12)),
Instruction::Ret,
],
stack_pos: -16,
stack_size: 16,
};

assert_eq!(actual.unwrap(), expected);
Expand All @@ -63,7 +63,7 @@ fn function() {
#[test]
fn instruction_unary() {
let mut stack_addrs: HashMap<String, i64> = HashMap::new();
let mut stack_pos: i64 = 0;
let mut stack_size = 0;

let actual: Vec<Instruction> = Instruction::codegen(ir::Instruction::Unary(
ir::UnaryOperator::Negation,
Expand All @@ -72,7 +72,7 @@ fn instruction_unary() {
))
.unwrap()
.into_iter()
.map(|instr| instr.replace_pseudo(&mut stack_pos, &mut stack_addrs))
.map(|instr| instr.replace_pseudo(&mut stack_size, &mut stack_addrs))
.collect();
let expected = vec![
Instruction::Mov(Operand::Stack(-4), Operand::Immediate(5)),
Expand Down Expand Up @@ -118,17 +118,17 @@ fn operand_from_val() {
#[test]
fn operand_replace_psuedo() {
let mut stack_addrs: HashMap<String, i64> = HashMap::new();
let mut stack_pos: i64 = 0;
let mut stack_size = 0;
let operand =
Operand::Pseudo(Identifier::new("x")).replace_pseudo(&mut stack_pos, &mut stack_addrs);
Operand::Pseudo(Identifier::new("x")).replace_pseudo(&mut stack_size, &mut stack_addrs);
let operand2 =
Operand::Pseudo(Identifier::new("x")).replace_pseudo(&mut stack_pos, &mut stack_addrs);
Operand::Pseudo(Identifier::new("x")).replace_pseudo(&mut stack_size, &mut stack_addrs);
let operand3 =
Operand::Pseudo(Identifier::new("y")).replace_pseudo(&mut stack_pos, &mut stack_addrs);
Operand::Pseudo(Identifier::new("y")).replace_pseudo(&mut stack_size, &mut stack_addrs);
assert_eq!(Operand::Stack(-4), operand);
assert_eq!(Operand::Stack(-4), operand2);
assert_eq!(Operand::Stack(-8), operand3);
assert_eq!(-8, stack_pos);
assert_eq!(8, stack_size);
assert_eq!(2, stack_addrs.len());
}

Expand All @@ -141,7 +141,7 @@ mod emit {
body: vec![Function {
name: Identifier::new("main"),
instructions: vec![Instruction::AllocateStack(16), Instruction::Ret],
stack_pos: -4,
stack_size: 4,
}],
}
.emit();
Expand All @@ -162,7 +162,7 @@ mod emit {
let actual = Function {
name: Identifier::new("main"),
instructions: vec![Instruction::AllocateStack(4), Instruction::Ret],
stack_pos: -4,
stack_size: 4,
}
.emit();

Expand Down
65 changes: 29 additions & 36 deletions src/codegen/x86_64/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub enum CodegenError {
}

type CodegenResult<T> = Result<T, CodegenError>;
type StackAddrMap = HashMap<String, i64>;

#[derive(Debug, PartialEq)]
#[allow(dead_code)]
Expand Down Expand Up @@ -65,7 +66,7 @@ impl fmt::Display for Program {
pub struct Function {
pub name: Identifier,
pub instructions: Vec<Instruction>,
pub stack_pos: i64,
pub stack_size: usize,
}

impl Function {
Expand Down Expand Up @@ -125,7 +126,7 @@ impl Function {
let result = Self {
name: Identifier::codegen(function.name),
instructions,
stack_pos: -(prologue_stack_size as i64),
stack_size: prologue_stack_size,
}
.replace_pseudo()
.fixup();
Expand All @@ -134,23 +135,22 @@ impl Function {
}

fn replace_pseudo(mut self) -> Self {
let mut stack_addrs: HashMap<String, i64> = HashMap::new();
let mut stack_addrs: StackAddrMap = HashMap::new();

self.instructions = self
.instructions
.into_iter()
.map(|instr| instr.replace_pseudo(&mut self.stack_pos, &mut stack_addrs))
.map(|instr| instr.replace_pseudo(&mut self.stack_size, &mut stack_addrs))
.collect();

self
}

fn fixup(mut self) -> Self {
// Round up to nearest multiple of 16 to align for calls
// TODO: this whole mess with negative i64/usize stack pos needs to end
self.stack_pos = -(((-self.stack_pos + 15) / 16) * 16);
self.stack_size = ((self.stack_size + 15) / 16) * 16;
self.instructions
.insert(0, Instruction::AllocateStack(-self.stack_pos));
.insert(0, Instruction::AllocateStack(self.stack_size));

self.instructions = self
.instructions
Expand Down Expand Up @@ -198,8 +198,8 @@ pub enum Instruction {
JmpCC(CondCode, Identifier),
SetCC(CondCode, Operand),
Label(Identifier),
AllocateStack(i64),
DeallocateStack(i64),
AllocateStack(usize),
DeallocateStack(usize),
Push(Operand),
Call(Identifier),
Ret,
Expand Down Expand Up @@ -334,9 +334,9 @@ impl Instruction {

// Adjust SP
instructions.push(Instruction::Call(Identifier::codegen(name)));
let stack_bytes = 8 * stack_args.len() as i64 + stack_padding;
let stack_bytes = 8 * stack_args.len() + stack_padding;
if stack_bytes != 0 {
instructions.push(Instruction::DeallocateStack(stack_bytes as i64));
instructions.push(Instruction::DeallocateStack(stack_bytes));
}

// Get return value
Expand All @@ -350,41 +350,37 @@ impl Instruction {
Ok(instructions)
}

pub fn replace_pseudo(
self,
stack_pos: &mut i64,
stack_addrs: &mut HashMap<String, i64>,
) -> Self {
pub fn replace_pseudo(self, stack_size: &mut usize, stack_addrs: &mut StackAddrMap) -> Self {
match self {
Instruction::Mov(dst, src) => {
let src = src.replace_pseudo(stack_pos, stack_addrs);
let dst = dst.replace_pseudo(stack_pos, stack_addrs);
let src = src.replace_pseudo(stack_size, stack_addrs);
let dst = dst.replace_pseudo(stack_size, stack_addrs);
Instruction::Mov(dst, src)
}
Instruction::Unary(op, dst) => {
let dst = dst.replace_pseudo(stack_pos, stack_addrs);
let dst = dst.replace_pseudo(stack_size, stack_addrs);
Instruction::Unary(op, dst)
}
Instruction::Binary(op, dst, src) => {
let src = src.replace_pseudo(stack_pos, stack_addrs);
let dst = dst.replace_pseudo(stack_pos, stack_addrs);
let src = src.replace_pseudo(stack_size, stack_addrs);
let dst = dst.replace_pseudo(stack_size, stack_addrs);
Instruction::Binary(op, dst, src)
}
Instruction::Idiv(src) => {
let src = src.replace_pseudo(stack_pos, stack_addrs);
let src = src.replace_pseudo(stack_size, stack_addrs);
Instruction::Idiv(src)
}
Instruction::SetCC(cc, dst) => {
let dst = dst.replace_pseudo(stack_pos, stack_addrs);
let dst = dst.replace_pseudo(stack_size, stack_addrs);
Instruction::SetCC(cc, dst)
}
Instruction::Cmp(op1, op2) => {
let op1 = op1.replace_pseudo(stack_pos, stack_addrs);
let op2 = op2.replace_pseudo(stack_pos, stack_addrs);
let op1 = op1.replace_pseudo(stack_size, stack_addrs);
let op2 = op2.replace_pseudo(stack_size, stack_addrs);
Instruction::Cmp(op1, op2)
}
Instruction::Push(operand) => {
Instruction::Push(operand.replace_pseudo(stack_pos, stack_addrs))
Instruction::Push(operand.replace_pseudo(stack_size, stack_addrs))
}
Instruction::Ret
| Instruction::Cdq
Expand Down Expand Up @@ -567,28 +563,25 @@ impl Operand {
}
}

fn pseudo_to_stack(&self, stack_pos: &mut i64, stack_addrs: &mut HashMap<String, i64>) -> Self {
fn pseudo_to_stack(&self, stack_size: &mut usize, stack_addrs: &mut StackAddrMap) -> Self {
if let Operand::Pseudo(name) = self {
let addr = if let Some(addr) = stack_addrs.get(&name.to_string()) {
*addr
} else {
*stack_pos -= 4;
stack_addrs.insert(name.to_string(), *stack_pos);
*stack_pos
*stack_size += 4;
let new_stack_offset = -(*stack_size as i64);
stack_addrs.insert(name.to_string(), new_stack_offset);
new_stack_offset
};
Operand::Stack(addr)
} else {
panic!("Fatal codegen error: {:?} is not a pseudo operand", self);
}
}

pub fn replace_pseudo(
self,
stack_pos: &mut i64,
stack_addrs: &mut HashMap<String, i64>,
) -> Self {
pub fn replace_pseudo(self, stack_size: &mut usize, stack_addrs: &mut StackAddrMap) -> Self {
if self.is_pseudo() {
self.pseudo_to_stack(stack_pos, stack_addrs)
self.pseudo_to_stack(stack_size, stack_addrs)
} else {
self
}
Expand Down

0 comments on commit c41aa1c

Please sign in to comment.