Skip to content

Commit

Permalink
feat(codegen-x86): Implement regalloc
Browse files Browse the repository at this point in the history
feat(xlang-backend): Support global_address
fix(rust-irgen): Generate proper code for local variables
  • Loading branch information
chorman0773 committed Aug 5, 2023
1 parent ee8c80d commit 3d58c6d
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 40 deletions.
226 changes: 190 additions & 36 deletions codegen-x86/src/mc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,29 @@ impl X86Tag {
X86Tag::RegisterWatcom => &[],
}
}

pub fn saved_regs(&self) -> &[X86Register] {
match self {
X86Tag::CDecl => todo!(),
X86Tag::Stdcall => todo!(),
X86Tag::Fastcall => todo!(),
X86Tag::Thiscall => todo!(),
X86Tag::Vectorcall => todo!(),
X86Tag::SysV64 => &[
X86Register::Rbx,
X86Register::Rsp,
X86Register::Rbp,
X86Register::R12,
X86Register::R13,
X86Register::R14,
X86Register::R15,
],
X86Tag::Win64 => todo!(),
X86Tag::Pascal => todo!(),
X86Tag::RegisterBorland => todo!(),
X86Tag::RegisterWatcom => todo!(),
}
}
}

#[allow(dead_code)]
Expand Down Expand Up @@ -298,7 +321,9 @@ impl MachineFeatures for X86MachineFeatures {
}
}

pub struct X86Clobbers {}
pub struct X86Clobbers {
used_regs: HashSet<X86Register>,
}

pub struct X86MCWriter {}

Expand Down Expand Up @@ -352,6 +377,87 @@ fn resolve_locations_in(
}
}

fn allocate_registers_for(
dest: &mut MaybeResolved<X86ValLocation>,
clobbers: &mut X86Clobbers,
assignments: &mut HashMap<u32, X86ValLocation>,
num: u32,
) -> bool {
let iregs = &[
X86Register::Rax,
X86Register::Rcx,
X86Register::Rdx,
X86Register::Rbx,
X86Register::Rsi,
X86Register::Rdi,
X86Register::R8,
X86Register::R9,
X86Register::R10,
X86Register::R11,
X86Register::R12,
X86Register::R13,
X86Register::R14,
X86Register::R15,
];
match dest {
MaybeResolved::Unresolved(loc) => {
if loc.size() == 0 {
let id = loc.id();
let loc = X86ValLocation::Null;
*dest = MaybeResolved::Resolved(Type::Null, loc.clone());
assignments.insert(id, loc);
false
} else if loc.size() <= 8 {
for reg in iregs {
if clobbers.used_regs.contains(reg) {
continue;
} else {
let id = loc.id();
let loc = X86ValLocation::Register(*reg);
*dest = MaybeResolved::Resolved(Type::Null, loc.clone());
assignments.insert(id, loc);
return false;
}
}
todo!("no available registers")
} else {
todo!("memory")
}
}
_ => true,
}
}

fn allocate_registers_in(
insn: &mut MCInsn<X86ValLocation>,
clobbers: &mut X86Clobbers,
assignments: &mut HashMap<u32, X86ValLocation>,
num: u32,
) -> bool {
match insn {
MCInsn::Null => true,
MCInsn::Mov { dest, src } => match (&mut *dest, src) {
(MaybeResolved::Unresolved(_), MaybeResolved::Unresolved(_)) => {
allocate_registers_for(dest, clobbers, assignments, num);
false
}
_ => true,
},
MCInsn::MovImm { dest, src } => allocate_registers_for(dest, clobbers, assignments, num),
MCInsn::StoreIndirect { dest_ptr, src, cl } => true,
MCInsn::Trap { kind } => true,
MCInsn::Barrier(_) => true,
MCInsn::BinaryOpImm { dest, val, op } => true,
MCInsn::BinaryOp { dest, src, op } => true,
MCInsn::UnaryOp { dest, op } => true,
MCInsn::CallSym(_) => true,
MCInsn::Return => true,
MCInsn::LoadSym { loc, sym } => allocate_registers_for(loc, clobbers, assignments, num),
MCInsn::Label(_) => true,
_ => true,
}
}

impl MCWriter for X86MCWriter {
type Features = X86MachineFeatures;

Expand All @@ -365,45 +471,93 @@ impl MCWriter for X86MCWriter {
callconv: &<Self::Features as xlang_backend::mc::MachineFeatures>::CallConv,
) -> Self::Clobbers {
let mut curr_assignments = HashMap::new();
let mut clobbers = X86Clobbers {
used_regs: HashSet::new(),
};
let iregs = &[
X86Register::Rax,
X86Register::Rcx,
X86Register::Rdx,
X86Register::Rbx,
X86Register::Rsi,
X86Register::Rdi,
X86Register::R8,
X86Register::R9,
X86Register::R10,
X86Register::R11,
X86Register::R12,
X86Register::R13,
X86Register::R14,
X86Register::R15,
];

let saved_reg = callconv.tag.saved_regs();

for reg in saved_reg {
clobbers.used_regs.insert(*reg).ok();
}

let mut done = false;
while !done {
done = true;
let mut outer_done = false;

for insn in insns.iter_mut() {
match insn {
xlang_backend::mc::MCInsn::Mov { dest, src } => match (dest, src) {
(MaybeResolved::Resolved(_, reg), MaybeResolved::Unresolved(loc)) => {
curr_assignments.insert(loc.id(), reg.clone());
done = false;
}
(MaybeResolved::Unresolved(loc), MaybeResolved::Resolved(_, reg)) => {
curr_assignments.insert(loc.id(), reg.clone());
done = false;
}
(MaybeResolved::Unresolved(l), MaybeResolved::Unresolved(r)) => {
if let Some(val) = curr_assignments.get(&l.id()) {
let val = val.clone();
curr_assignments.insert(r.id(), val);
while !outer_done {
outer_done = true;

let mut done = false;
while !done {
done = true;

for (insn, addr) in insns.iter_mut().zip(0u32..) {
match insn {
xlang_backend::mc::MCInsn::Mov { dest, src } => match (dest, src) {
(MaybeResolved::Resolved(_, reg), MaybeResolved::Unresolved(loc)) => {
match reg {
X86ValLocation::Register(reg) => {
let _ = clobbers.used_regs.insert(*reg);
}
_ => {}
}
curr_assignments.insert(loc.id(), reg.clone());
done = false;
} else if let Some(val) = curr_assignments.get(&r.id()) {
let val = val.clone();
curr_assignments.insert(r.id(), val);
}
(MaybeResolved::Unresolved(loc), MaybeResolved::Resolved(_, reg)) => {
match reg {
X86ValLocation::Register(reg) => {
let _ = clobbers.used_regs.insert(*reg);
}
_ => {}
}
curr_assignments.insert(loc.id(), reg.clone());
done = false;
}
}
(MaybeResolved::Unresolved(l), MaybeResolved::Unresolved(r)) => {
if let Some(val) = curr_assignments.get(&l.id()) {
let val = val.clone();
curr_assignments.insert(r.id(), val);
done = false;
} else if let Some(val) = curr_assignments.get(&r.id()) {
let val = val.clone();
curr_assignments.insert(r.id(), val);
done = false;
} else {
}
}
_ => {}
},
_ => {}
},
_ => {}
}
}

for insn in insns.iter_mut() {
resolve_locations_in(insn, &curr_assignments);
}
}

for insn in insns.iter_mut() {
resolve_locations_in(insn, &curr_assignments);
for (insn, num) in insns.iter_mut().zip(0u32..) {
outer_done &=
allocate_registers_in(insn, &mut clobbers, &mut curr_assignments, num);
}
}

X86Clobbers {}
clobbers
}

fn write_machine_code<I: arch_ops::traits::InsnWrite, F: FnMut(String, u64)>(
Expand All @@ -417,15 +571,15 @@ impl MCWriter for X86MCWriter {
) -> std::io::Result<()> {
let mut encoder = X86Encoder::new(out, X86Mode::Long);
let mut frame_size = 0u32;
for insn in insns {
for insn in insns.iter() {
match insn {
MCInsn::Null => {}
MCInsn::Mov { dest, src } => {
if dest == src {
// no-op
} else {
match (dest, src) {
(MaybeResolved::Resolved(_, dest), MaybeResolved::Resolved(_, src)) => {
match (dest, src) {
(MaybeResolved::Resolved(_, dest), MaybeResolved::Resolved(_, src)) => {
if dest == src {
// no-op
} else {
match (dest, src) {
(X86ValLocation::Null, _) | (_, X86ValLocation::Null) => {}
(
Expand Down Expand Up @@ -470,8 +624,8 @@ impl MCWriter for X86MCWriter {
_ => todo!(),
}
}
_ => panic!("Unresolved locations made it to write_machine_code"),
}
_ => panic!("Unresolved locations made it to write_machine_code"),
}
}
MCInsn::MovImm { dest, src } => match dest {
Expand Down
11 changes: 8 additions & 3 deletions rust/src/irgen/xir_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1283,12 +1283,13 @@ impl<'a> JumpVisitor for XirJumpVisitor<'a> {
let targets = self
.targs
.get_or_insert_with_mut(self.targ.expect("wrong visit order"), |_| Vec::new());
let height = targets.len() as u32;
targets.push(ir::StackItem {
ty: self.ssa_tys[&src].clone(),
kind: ir::StackValueKind::RValue,
});
self.ssa_tys.insert(dest, self.ssa_tys[&src].clone());
self.var_heights.insert(dest, self.var_heights[&src]);
self.var_heights.insert(dest, height);
}
}

Expand Down Expand Up @@ -1440,8 +1441,12 @@ impl<'a> ExprVisitor for XirExprVisitor<'a> {

fn visit_var(&mut self, var: SsaVarId) {
let depth = (*self.stack_height) - self.var_heights[&var];
eprintln!(
"Depth of {}: {} (var_height: {})",
var, depth, self.var_heights[&var]
);

if depth == 0 {
if depth != 0 {
self.body
.block
.items
Expand All @@ -1452,7 +1457,7 @@ impl<'a> ExprVisitor for XirExprVisitor<'a> {
.block
.items
.push(ir::BlockItem::Expr(ir::Expr::Dup(1)));
if depth == 0 {
if depth != 0 {
self.body
.block
.items
Expand Down
8 changes: 7 additions & 1 deletion xlang/xlang_backend/src/mc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,13 @@ impl<F: MachineFeatures> FunctionRawCodegen for MCFunctionCodegen<F> {
}

fn compute_global_address(&mut self, path: &xlang::ir::Path, loc: Self::Loc) {
todo!()
let sym = match &*path.components {
[xlang::ir::PathComponent::Root, xlang::ir::PathComponent::Text(text)]
| [xlang::ir::PathComponent::Text(text)] => text.to_string(),
[xlang::ir::PathComponent::Root, rest @ ..] | [rest @ ..] => self.inner.mangle(rest),
};

self.mc_insns.push(MCInsn::LoadSym { loc, sym });
}

fn compute_label_address(&mut self, target: u32, loc: Self::Loc) {
Expand Down

0 comments on commit 3d58c6d

Please sign in to comment.