r9ir 1.0.0

Rewrite 9cc in Rust
Documentation
#![allow(non_camel_case_types)]

use crate::gen_ir::*;
use crate::parse::*;
use std::cell::RefCell;
use std::rc::Rc;

fn regno(r: Option<Rc<RefCell<Reg>>>) -> i32 {
    if r.is_none() {
        return 0;
    }
    let rr = r.unwrap().clone();
    let rn = rr.borrow().rn;
    if rn != -1 {
        return rr.borrow().rn;
    }
    return rr.borrow().vn;
}

fn tostr_call(ir: & IR) -> String {
    let mut s = String::new();
    s.push_str(&format!("r{} = {}(", regno(ir.r0.clone()), ir.name));
    for i in 0..ir.nargs {
        if i != 0 {
            s.push_str(", ");
        }
        s.push_str(&format!("r{}", regno(Some(ir.args[i].clone()))));
    }
    s.push_str(")");
    return s;
}

pub fn tostr(ir: & IR) -> String {
    let r0 = regno(ir.r0.clone());
    let r1 = regno(ir.r1.clone());
    let r2 = regno(ir.r2.clone());

    match ir.op {
        IRType::ADD => format!("r{} = r{} + r{}", r0, r1, r2),
        IRType::CALL => tostr_call(ir),
        IRType::DIV => format!("r{} = r{} / r{}", r0, r1, r2),
        IRType::IMM => format!("r{} = {}", r0, ir.imm),
        IRType::JMP => {
            let bb1 = ir.bb1.clone().unwrap();
            let bbarg = ir.bbarg.clone();
            if bbarg.is_some() {
                return format!("JMP .L{} (r{})", bb1.borrow().label, regno(bbarg))
            }
            return format!("JMP .L{}", bb1.borrow().label);
        }
        IRType::LABEL_ADDR => format!("r{} = .L{}", r0, ir.label),
        IRType::EQ => format!("r{} = r{} == r{}", r0, r1, r2),
        IRType::NE => format!("r{} = r{} != r{}", r0, r1, r2),
        IRType::LE => format!("r{} = r{} <= r{}", r0, r1, r2),
        IRType::LT => format!("r{} = r{} < r{}", r0, r1, r2),
        IRType::AND => format!("r{} = r{} & r{}", r0, r1, r2),
        IRType::OR => format!("r{} = r{} | r{}", r0, r1, r2),
        IRType::XOR => format!("r{} = r{} ^ r{}", r0, r1, r2),
        IRType::SHL => format!("r{} = r{} << r{}", r0, r1, r2),
        IRType::SHR => format!("r{} = r{} >> r{}", r0, r1, r2),
        IRType::LOAD => format!("LOAD{} r{}, r{}", ir.size, r0, r2),
        IRType::LOAD_SPILL => format!("LOAD_SPILL r{}, {}", r0, ir.imm),
        IRType::MOD => format!("r{} = r{} % r{}", r0, r1, r2),
        IRType::MOV => format!("r{} = r{}", r0, r2),
        IRType::MUL => format!("r{} = r{} * r{}", r0, r1, r2),
        IRType::NOP => "NOP".to_string(),
        IRType::RETURN => format!("RET r{}", r2),
        IRType::STORE => format!("STORE{} r{}, r{}", ir.size, r1, r2),
        IRType::STORE_ARG => {
            let var = ir.var.clone().unwrap();
            let name = var.borrow().name.clone();
            let offset = var.borrow().offset;
            format!("STORE_ARG{} {} {} ({})", ir.size, ir.imm, name, offset)
        }
        IRType::STORE_SPILL => format!("STORE_SPILL r{}, {}", r1, ir.imm),
        IRType::SUB => format!("r{} = r{} - r{}", r0, r1, r2),
        IRType::BPREL => {
            let var = ir.var.clone().unwrap();
            let name = var.borrow().name.clone();
            let offset = var.borrow().offset;
            format!("BPREL r{} {} ({})", r0, name, offset)
        }
        IRType::BR => {
            let bb1 = ir.bb1.clone().unwrap();
            let bb2 = ir.bb2.clone().unwrap();
            return format!("BR r{} .L{} .L{}", r2, bb1.borrow().label, bb2.borrow().label);
        }
    }
}

fn print_rel(name: & str, v: Vec<Rc<RefCell<BB>>>) {
    if v.len() == 0 {
        return;
    }
    eprint!(" {}=", name);
    for i in 0..v.len() {
        let bb = &v[i];
        if i > 0 {
            eprint!(",");
        }
        eprint!(".L{}", bb.borrow().label);
    }
}

fn print_regs(name: & str, v: Vec<Rc<RefCell<Reg>>>) {
    if v.len() == 0 {
        return;
    }
    eprint!(" {}=", name);
    for i in 0..v.len() {
        let r = &v[i];
        if i > 0 {
            eprint!(",");
        }
        eprint!("r{}", regno(Some(r.clone())));
    }
}

fn print_bb(bb: Rc<RefCell<BB>>) {
    let label = bb.borrow().label.clone();
    let param = bb.borrow().param.clone();
    if param.is_some() {
        eprint!(".L{}({})", label, regno(param));
    } else {
        eprint!(".L{}", label);
    }

    print_rel("pred", bb.borrow().pred.clone());
    print_rel("succ", bb.borrow().succ.clone());
    let def_regs = bb.borrow().def_regs.clone();
    let in_regs = bb.borrow().in_regs.clone();
    let out_regs = bb.borrow().out_regs.clone();
    print_regs("defs", def_regs.borrow().clone());
    print_regs("in", in_regs.borrow().clone());
    print_regs("out", out_regs.borrow().clone());
    eprintln!();
}

pub fn dump_ir(irv: Vec<Rc<RefCell<Function>>>) {
    for fun in irv.iter() {
        eprintln!("{}:", fun.borrow().name);

        for bb in fun.borrow().bbs.iter() {
            print_bb(bb.clone());

            for i in bb.borrow().ir.iter() {
                eprintln!("\t{}", tostr(&i.borrow()).to_string());
            }
        }
    }
}