Files
rusty-minic/src/ir/types.rs
T
2026-05-09 19:55:23 +08:00

167 lines
5.2 KiB
Rust

use std::fmt::Display;
use crate::ast::types::Type as AstType;
use crate::ast::types::BinaryOp as AstBinaryOp;
use crate::ir::err::IRError;
pub enum IRInstr {
Declare(Variable),
DefineFunc(Function, Vec<Variable>, Vec<IRInstr>),
Entry,
Binary(Variable, Variable, BinaryOp, Variable),
Exit(Option<Variable>),
FuncCall(Function, Vec<Variable>, Option<Variable>),
// Goto,
// Label,
Move(Variable, MoveRValue),
}
impl Display for IRInstr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
IRInstr::Entry => write!(f, "entry"),
IRInstr::Binary(dest, left, op, right) => write!(f, "{} = {} {} {}", dest, op, left, right),
IRInstr::Exit(v) => if let Some(v) = v { write!(f, "exit {}", v) } else { write!(f, "exit") },
IRInstr::FuncCall(func, args, dest) => {
if let Some(dest) = dest {
write!(f, "{} = call {}", dest, func.to_call_string(args))
} else {
write!(f, "call {}", func.to_call_string(args))
}
}
IRInstr::Move(dest, src) => write!(f, "{} = {}", dest, src),
IRInstr::Declare(var) => write!(f, "declare {} {}", var.data_type, var),
IRInstr::DefineFunc(func, args, body) => {
let body_str = body.iter().map(|instr| format!(" {}", instr)).collect::<Vec<_>>().join("\n");
write!(f, "define {} {{\n{}\n}}", func.to_decl_string(args), body_str)
}
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum IRType {
I32,
I1,
Void,
}
impl Display for IRType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
IRType::I32 => write!(f, "i32"),
IRType::Void => write!(f, "void"),
IRType::I1 => write!(f, "i1"),
}
}
}
impl From<AstType> for IRType {
fn from(ast_type: AstType) -> Self {
match ast_type {
AstType::Int => IRType::I32,
AstType::Void => IRType::Void,
}
}
}
pub enum MoveRValue {
Var(Variable),
ConstInt(i32),
}
impl Display for MoveRValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MoveRValue::Var(v) => write!(f, "{}", v),
MoveRValue::ConstInt(i) => write!(f, "{}", i),
}
}
}
#[derive(Clone, Copy)]
pub enum VariableType {
Global,
ParamTemp,
Local,
Temp,
}
#[derive(Clone, Copy)]
pub struct Variable {
// pub name: String,
pub index: usize,
pub var_type: VariableType,
pub data_type: IRType,
}
impl Display for Variable {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let prefix = match self.var_type {
VariableType::Global => "@",
VariableType::Local => "%l",
VariableType::Temp => "%t",
VariableType::ParamTemp => "%t",
};
write!(f, "{}{}", prefix, self.index)
}
}
#[derive(Debug, Clone)]
pub struct Function {
pub name: String,
pub return_type: IRType,
pub parameter_types: Vec<IRType>,
// pub parameters: Vec<Variable>,
}
impl Function {
pub fn to_call_string(&self, args: &Vec<Variable>) -> String {
assert!(args.len() == self.parameter_types.len());
let args_str = args.iter().zip(self.parameter_types.iter()).map(|(arg, param)| format!("{} {}", param, arg)).collect::<Vec<_>>().join(", ");
format!("{} @{}({})", self.return_type, self.name, args_str)
}
pub fn to_decl_string(&self, args: &Vec<Variable>) -> String {
let params_str = args.iter().zip(self.parameter_types.iter()).map(|(arg, param_type)| format!("{} {}", param_type, arg)).collect::<Vec<_>>().join(", ");
format!("{} @{}({})", self.return_type, self.name, params_str)
}
}
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
Mod,
Le,
Lt,
Gt,
Ge,
Ne,
Eq,
}
impl Display for BinaryOp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let op_str = match self {
BinaryOp::Add => "add",
BinaryOp::Sub => "sub",
BinaryOp::Mul => "mul",
BinaryOp::Div => "div",
BinaryOp::Mod => "mod",
BinaryOp::Le => "le",
BinaryOp::Lt => "lt",
BinaryOp::Gt => "gt",
BinaryOp::Ge => "ge",
BinaryOp::Ne => "ne",
BinaryOp::Eq => "eq",
};
write!(f, "{}", op_str)
}
}
impl From<AstBinaryOp> for BinaryOp {
fn from(ast_op: AstBinaryOp) -> Self {
match ast_op {
AstBinaryOp::Add => BinaryOp::Add,
AstBinaryOp::Sub => BinaryOp::Sub,
AstBinaryOp::Mul => BinaryOp::Mul,
AstBinaryOp::Div => BinaryOp::Div,
AstBinaryOp::Mod => BinaryOp::Mod,
AstBinaryOp::Equal => BinaryOp::Eq,
AstBinaryOp::NotEqual => BinaryOp::Ne,
AstBinaryOp::Less => BinaryOp::Lt,
AstBinaryOp::LessEqual => BinaryOp::Le,
AstBinaryOp::Greater => BinaryOp::Gt,
AstBinaryOp::GreaterEqual => BinaryOp::Ge,
}
}
}