28f917ef by Ulrich Schoepp

Backend-Interfaces Rust

1 parent 66c9092c
use std::fmt::{Debug, Display};
use ident::{Ident, Label};
use tree;
pub trait MachineInstr {
type UseIterator: Iterator<Item = Ident>;
type DefIterator: Iterator<Item = Ident>;
type TargetIterator: Iterator<Item = Label>;
fn uses(&self) -> Self::UseIterator;
fn defs(&self) -> Self::DefIterator;
fn is_fall_through(&self) -> bool;
fn jumps(&self) -> Self::TargetIterator;
fn is_move_between_temps(&self) -> Option<(Ident, Ident)>;
fn is_label(&self) -> Option<Label>;
fn rename(&mut self, sigma: &Fn(Ident) -> Ident);
}
pub trait MachineFunction<A: MachineInstr>: Debug {
fn name(&self) -> &Label;
fn body(&self) -> &Vec<A>;
fn spill(&mut self, to_spill: &Vec<Ident>);
fn rename(&mut self, sigma: &Fn(Ident) -> Ident);
}
pub trait MachinePrg<A: MachineInstr, F: MachineFunction<A>>: Debug + Display {
fn functions(&self) -> &Vec<F>;
fn functions_mut(&mut self) -> &mut Vec<F>;
}
pub trait CodeGen<A: MachineInstr, F: MachineFunction<A>, P: MachinePrg<A, F>> {
fn all_registers() -> Vec<Ident>;
fn general_purpose_registers() -> Vec<Ident>;
fn code_gen(c: tree::Prg) -> P;
}
use std::fmt::{Debug, Display, Formatter, Error};
use x86::{X86Function, X86Prg};
use x86::x86instr;
impl Display for x86instr::UnaryInstr {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
Debug::fmt(self, fmt)
}
}
impl Display for x86instr::BinaryInstr {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
Debug::fmt(self, fmt)
}
}
impl Display for x86instr::JumpCond {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
Debug::fmt(self, fmt)
}
}
impl Display for x86instr::Scale {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
use self::x86instr::Scale::*;
match *self {
S1 => write!(fmt, "1"),
S2 => write!(fmt, "2"),
S4 => write!(fmt, "4"),
S8 => write!(fmt, "8"),
}
}
}
impl Display for x86instr::EffectiveAddress {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match (self.base, self.index_scale) {
(None, None) => write!(fmt, "{}", self.displacement),
(None, Some((i, s))) => write!(fmt, "{}*{} + {}", i, s, self.displacement),
(Some(b), None) => write!(fmt, "{} + {}", b, self.displacement),
(Some(b), Some((i, s))) => write!(fmt, "{} + {}*{} + {}", b, i, s, self.displacement),
}
}
}
impl Display for x86instr::Operand {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
use self::x86instr::Operand::*;
match *self {
Imm(n) => write!(fmt, "{}", n),
Reg(i) => write!(fmt, "{}", i),
Mem(i) => write!(fmt, "DWORD PTR [{}]", i),
}
}
}
impl Display for x86instr::X86Instr {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
use self::x86instr::X86Instr::*;
match *self {
Unary(i, ref o) => {
write!(fmt, "{} {}", i, o)
}
Binary(b, ref o1, ref o2) => {
write!(fmt, "{} {} , {}", b, o1, o2)
}
Label(ref l) => {
write!(fmt, "{}:", l)
}
JMP(ref l) => {
write!(fmt, "JMP {}", l)
}
CALL(ref l) => {
write!(fmt, "CALL {}", l)
}
J(ref c, ref l) => {
write!(fmt, "J{} {}", c, l)
}
RET => write!(fmt, "RET"),
}
}
}
impl Display for X86Function {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
use backend::MachineFunction;
write!(fmt, "{}:\n", self.name())?;
for i in self.body() {
writeln!(fmt, "{}", i)?
}
Ok(())
}
}
impl Display for X86Prg {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
writeln!(fmt, " .intel_syntax")?;
writeln!(fmt, " .global Lmain")?;
for f in &self.functions {
writeln!(fmt, "{}\n", f)?
}
Ok(())
}
}
pub use self::x86instr::X86Instr;
pub use self::x86function::X86Function;
pub use self::x86prg::X86Prg;
mod x86instr;
mod x86function;
mod x86prg;
mod display;
use ident::{Ident, Label};
use backend;
use x86::X86Instr;
#[derive(Debug)]
pub struct X86Function {
pub name: Label,
pub body: Vec<X86Instr>,
locals_in_stack: usize,
}
impl X86Function {
pub fn new(name: Label, body: Vec<X86Instr>) -> X86Function {
X86Function {
name: name,
body: body,
locals_in_stack: 0,
}
}
}
impl backend::MachineFunction<X86Instr> for X86Function {
fn name(&self) -> &Label {
&self.name
}
fn body(&self) -> &Vec<X86Instr> {
&self.body
}
fn spill(&mut self, _to_spill: &Vec<Ident>) {
panic!("needed later for register allocation")
}
fn rename(&mut self, _sigma: &Fn(Ident) -> Ident) {
panic!("needed later for register allocation")
}
}
use ident::{Ident, Label};
use backend;
#[derive(Debug, Copy, Clone)]
pub enum UnaryInstr {
PUSH,
POP,
NEG,
NOT,
INC,
DEC,
IDIV,
}
#[derive(Debug, Copy, Clone)]
pub enum BinaryInstr {
MOV,
ADD,
SUB,
SHL,
SHR,
SAL,
SAR,
AND,
OR,
XOR,
TEST,
CMP,
LEA,
IMUL,
}
#[derive(Debug, Copy, Clone)]
pub enum JumpCond {
E,
NE,
L,
LE,
G,
GE,
Z,
}
#[derive(Debug, Copy, Clone)]
pub enum Scale {
S1,
S2,
S4,
S8,
}
#[derive(Debug, Copy, Clone)]
pub struct EffectiveAddress {
pub base: Option<Ident>,
pub index_scale: Option<(Ident, Scale)>,
pub displacement: i32,
}
#[derive(Debug, Clone)]
pub enum Operand {
Imm(i32),
Reg(Ident),
Mem(EffectiveAddress),
}
#[derive(Debug)]
pub enum X86Instr {
Unary(UnaryInstr, Operand),
Binary(BinaryInstr, Operand, Operand),
Label(Label),
JMP(Label),
// only static calls needed for now
CALL(Label),
J(JumpCond, Label),
RET,
}
impl EffectiveAddress {
fn rename(&mut self, sigma: &Fn(Ident) -> Ident) {
self.base = match self.base {
None => None,
Some(t) => Some(sigma(t)),
};
match self.index_scale {
None => (),
Some((i, s)) => self.index_scale = Some((sigma(i), s)),
}
}
}
pub struct TargetIterator(Option<Label>);
impl Iterator for TargetIterator {
type Item = Label;
fn next(&mut self) -> Option<Label> {
match *self {
TargetIterator(None) => None,
TargetIterator(Some(l)) => {
*self = TargetIterator(None);
Some(l)
}
}
}
}
impl backend::MachineInstr for X86Instr {
// vector iterators are just one possibility here
type UseIterator = ::std::vec::IntoIter<Ident>;
type DefIterator = ::std::vec::IntoIter<Ident>;
type TargetIterator = ::std::vec::IntoIter<Label>;
fn uses(&self) -> Self::UseIterator {
panic!("needed later for register allocation")
}
fn defs(&self) -> Self::DefIterator {
panic!("needed later for register allocation")
}
fn is_fall_through(&self) -> bool {
panic!("needed later for register allocation")
}
fn jumps(&self) -> Self::TargetIterator {
panic!("needed later for register allocation")
}
fn is_move_between_temps(&self) -> Option<(Ident, Ident)> {
panic!("needed later for register allocation")
}
fn is_label(&self) -> Option<Label> {
panic!("needed later for register allocation")
}
fn rename(&mut self, _sigma: &Fn(Ident) -> Ident) {
panic!("needed later for register allocation")
}
}
use backend::MachinePrg;
use x86::X86Instr;
use x86::X86Function;
#[derive(Debug)]
pub struct X86Prg {
pub functions: Vec<X86Function>,
}
impl MachinePrg<X86Instr, X86Function> for X86Prg {
fn functions(&self) -> &Vec<X86Function> {
&self.functions
}
fn functions_mut(&mut self) -> &mut Vec<X86Function> {
&mut self.functions
}
}
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!