Emit IL alongside raw IC10 for use in future optimization passes
This commit is contained in:
8
rust_compiler/libs/il/Cargo.toml
Normal file
8
rust_compiler/libs/il/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "il"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
helpers = { path = "../helpers" }
|
||||
rust_decimal = { workspace = true }
|
||||
286
rust_compiler/libs/il/src/lib.rs
Normal file
286
rust_compiler/libs/il/src/lib.rs
Normal file
@@ -0,0 +1,286 @@
|
||||
use helpers::Span;
|
||||
use rust_decimal::Decimal;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
|
||||
pub struct InstructionNode<'a> {
|
||||
pub instruction: Instruction<'a>,
|
||||
pub span: Option<Span>,
|
||||
}
|
||||
|
||||
impl<'a> InstructionNode<'a> {
|
||||
pub fn new(instr: Instruction<'a>, span: Option<Span>) -> Self {
|
||||
Self {
|
||||
span,
|
||||
instruction: instr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the different types of operands available in IC10.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Operand<'a> {
|
||||
/// A hardware register (r0-r15)
|
||||
Register(u8),
|
||||
/// A device alias or direct connection (d0-d5, db)
|
||||
Device(Cow<'a, str>),
|
||||
/// A numeric literal (integer or float)
|
||||
Number(Decimal),
|
||||
/// A label used for jumping
|
||||
Label(Cow<'a, str>),
|
||||
/// A logic type string (e.g., "Temperature", "Open")
|
||||
LogicType(Cow<'a, str>),
|
||||
/// Special register: Stack Pointer
|
||||
StackPointer,
|
||||
/// Special register: Return Address
|
||||
ReturnAddress,
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for Operand<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Operand::Register(r) => write!(f, "r{}", r),
|
||||
Operand::Device(d) => write!(f, "{}", d),
|
||||
Operand::Number(n) => write!(f, "{}", n),
|
||||
Operand::Label(l) => write!(f, "{}", l),
|
||||
Operand::LogicType(t) => write!(f, "{}", t),
|
||||
Operand::StackPointer => write!(f, "sp"),
|
||||
Operand::ReturnAddress => write!(f, "ra"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a single IC10 MIPS instruction.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Instruction<'a> {
|
||||
/// `move dst val` - Copy value to register
|
||||
Move(Operand<'a>, Operand<'a>),
|
||||
|
||||
/// `add dst a b` - Addition
|
||||
Add(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `sub dst a b` - Subtraction
|
||||
Sub(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `mul dst a b` - Multiplication
|
||||
Mul(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `div dst a b` - Division
|
||||
Div(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `mod dst a b` - Modulo
|
||||
Mod(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `pow dst a b` - Power
|
||||
Pow(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `acos dst a`
|
||||
Acos(Operand<'a>, Operand<'a>),
|
||||
/// `asin dst a`
|
||||
Asin(Operand<'a>, Operand<'a>),
|
||||
/// `atan dst a`
|
||||
Atan(Operand<'a>, Operand<'a>),
|
||||
/// `atan2 dst a b`
|
||||
Atan2(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `abs dst a`
|
||||
Abs(Operand<'a>, Operand<'a>),
|
||||
/// `ceil dst a`
|
||||
Ceil(Operand<'a>, Operand<'a>),
|
||||
/// `cos dst a`
|
||||
Cos(Operand<'a>, Operand<'a>),
|
||||
/// `floor dst a`
|
||||
Floor(Operand<'a>, Operand<'a>),
|
||||
/// `log dst a`
|
||||
Log(Operand<'a>, Operand<'a>),
|
||||
/// `max dst a b`
|
||||
Max(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `min dst a b`
|
||||
Min(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `rand dst`
|
||||
Rand(Operand<'a>),
|
||||
/// `sin dst a`
|
||||
Sin(Operand<'a>, Operand<'a>),
|
||||
/// `sqrt dst a`
|
||||
Sqrt(Operand<'a>, Operand<'a>),
|
||||
/// `tan dst a`
|
||||
Tan(Operand<'a>, Operand<'a>),
|
||||
/// `trunc dst a`
|
||||
Trunc(Operand<'a>, Operand<'a>),
|
||||
|
||||
/// `l register device type` - Load from device
|
||||
Load(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `s device type value` - Set on device
|
||||
Store(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
|
||||
/// `ls register device slot type` - Load Slot
|
||||
LoadSlot(Operand<'a>, Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `ss device slot type value` - Set Slot
|
||||
StoreSlot(Operand<'a>, Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
|
||||
/// `lb register deviceHash type batchMode` - Load Batch
|
||||
LoadBatch(Operand<'a>, Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `sb deviceHash type value` - Set Batch
|
||||
StoreBatch(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
|
||||
/// `lbn register deviceHash nameHash type batchMode` - Load Batch Named
|
||||
LoadBatchNamed(
|
||||
Operand<'a>,
|
||||
Operand<'a>,
|
||||
Operand<'a>,
|
||||
Operand<'a>,
|
||||
Operand<'a>,
|
||||
),
|
||||
/// `sbn deviceHash nameHash type value` - Set Batch Named
|
||||
StoreBatchNamed(Operand<'a>, Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
|
||||
/// `j label` - Unconditional Jump
|
||||
Jump(Operand<'a>),
|
||||
/// `jal label` - Jump and Link (Function Call)
|
||||
JumpAndLink(Operand<'a>),
|
||||
/// `jr offset` - Jump Relative
|
||||
JumpRelative(Operand<'a>),
|
||||
|
||||
/// `beq a b label` - Branch if Equal
|
||||
BranchEq(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `bne a b label` - Branch if Not Equal
|
||||
BranchNe(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `bgt a b label` - Branch if Greater Than
|
||||
BranchGt(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `blt a b label` - Branch if Less Than
|
||||
BranchLt(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `bge a b label` - Branch if Greater or Equal
|
||||
BranchGe(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `ble a b label` - Branch if Less or Equal
|
||||
BranchLe(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `beqz a label` - Branch if Equal Zero
|
||||
BranchEqZero(Operand<'a>, Operand<'a>),
|
||||
/// `bnez a label` - Branch if Not Equal Zero
|
||||
BranchNeZero(Operand<'a>, Operand<'a>),
|
||||
|
||||
/// `seq dst a b` - Set if Equal
|
||||
SetEq(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `sne dst a b` - Set if Not Equal
|
||||
SetNe(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `sgt dst a b` - Set if Greater Than
|
||||
SetGt(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `slt dst a b` - Set if Less Than
|
||||
SetLt(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `sge dst a b` - Set if Greater or Equal
|
||||
SetGe(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `sle dst a b` - Set if Less or Equal
|
||||
SetLe(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
|
||||
/// `and dst a b` - Logical AND
|
||||
And(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `or dst a b` - Logical OR
|
||||
Or(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// `xor dst a b` - Logical XOR
|
||||
Xor(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
|
||||
/// `push val` - Push to Stack
|
||||
Push(Operand<'a>),
|
||||
/// `pop dst` - Pop from Stack
|
||||
Pop(Operand<'a>),
|
||||
/// `peek dst` - Peek from Stack (Usually sp - 1)
|
||||
Peek(Operand<'a>),
|
||||
/// `get dst dev num`
|
||||
Get(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
/// put dev addr val
|
||||
Put(Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
|
||||
/// `select dst cond a b` - Ternary Select
|
||||
Select(Operand<'a>, Operand<'a>, Operand<'a>, Operand<'a>),
|
||||
|
||||
/// `yield` - Pause execution
|
||||
Yield,
|
||||
/// `sleep val` - Sleep for seconds
|
||||
Sleep(Operand<'a>),
|
||||
|
||||
/// `alias name target` - Define Alias (Usually handled by compiler, but good for IR)
|
||||
Alias(Cow<'a, str>, Operand<'a>),
|
||||
/// `define name val` - Define Constant (Usually handled by compiler)
|
||||
Define(Cow<'a, str>, f64),
|
||||
|
||||
/// A label definition `Label:`
|
||||
LabelDef(Cow<'a, str>),
|
||||
|
||||
/// A comment `# text`
|
||||
Comment(Cow<'a, str>),
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for Instruction<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Instruction::Move(dst, val) => write!(f, "move {} {}", dst, val),
|
||||
Instruction::Add(dst, a, b) => write!(f, "add {} {} {}", dst, a, b),
|
||||
Instruction::Sub(dst, a, b) => write!(f, "sub {} {} {}", dst, a, b),
|
||||
Instruction::Mul(dst, a, b) => write!(f, "mul {} {} {}", dst, a, b),
|
||||
Instruction::Div(dst, a, b) => write!(f, "div {} {} {}", dst, a, b),
|
||||
Instruction::Mod(dst, a, b) => write!(f, "mod {} {} {}", dst, a, b),
|
||||
Instruction::Pow(dst, a, b) => write!(f, "pow {} {} {}", dst, a, b),
|
||||
Instruction::Acos(dst, a) => write!(f, "acos {} {}", dst, a),
|
||||
Instruction::Asin(dst, a) => write!(f, "asin {} {}", dst, a),
|
||||
Instruction::Atan(dst, a) => write!(f, "atan {} {}", dst, a),
|
||||
Instruction::Atan2(dst, a, b) => write!(f, "atan2 {} {} {}", dst, a, b),
|
||||
Instruction::Abs(dst, a) => write!(f, "abs {} {}", dst, a),
|
||||
Instruction::Ceil(dst, a) => write!(f, "ceil {} {}", dst, a),
|
||||
Instruction::Cos(dst, a) => write!(f, "cos {} {}", dst, a),
|
||||
Instruction::Floor(dst, a) => write!(f, "floor {} {}", dst, a),
|
||||
Instruction::Log(dst, a) => write!(f, "log {} {}", dst, a),
|
||||
Instruction::Max(dst, a, b) => write!(f, "max {} {} {}", dst, a, b),
|
||||
Instruction::Min(dst, a, b) => write!(f, "min {} {} {}", dst, a, b),
|
||||
Instruction::Rand(dst) => write!(f, "rand {}", dst),
|
||||
Instruction::Sin(dst, a) => write!(f, "sin {} {}", dst, a),
|
||||
Instruction::Sqrt(dst, a) => write!(f, "sqrt {} {}", dst, a),
|
||||
Instruction::Tan(dst, a) => write!(f, "tan {} {}", dst, a),
|
||||
Instruction::Trunc(dst, a) => write!(f, "trunc {} {}", dst, a),
|
||||
|
||||
Instruction::Load(reg, dev, typ) => write!(f, "l {} {} {}", reg, dev, typ),
|
||||
Instruction::Store(dev, typ, val) => write!(f, "s {} {} {}", dev, typ, val),
|
||||
Instruction::LoadSlot(reg, dev, slot, typ) => {
|
||||
write!(f, "ls {} {} {} {}", reg, dev, slot, typ)
|
||||
}
|
||||
Instruction::StoreSlot(dev, slot, typ, val) => {
|
||||
write!(f, "ss {} {} {} {}", dev, slot, typ, val)
|
||||
}
|
||||
Instruction::LoadBatch(reg, hash, typ, mode) => {
|
||||
write!(f, "lb {} {} {} {}", reg, hash, typ, mode)
|
||||
}
|
||||
Instruction::StoreBatch(hash, typ, val) => write!(f, "sb {} {} {}", hash, typ, val),
|
||||
Instruction::LoadBatchNamed(reg, d_hash, n_hash, typ, mode) => {
|
||||
write!(f, "lbn {} {} {} {} {}", reg, d_hash, n_hash, typ, mode)
|
||||
}
|
||||
Instruction::StoreBatchNamed(d_hash, n_hash, typ, val) => {
|
||||
write!(f, "sbn {} {} {} {}", d_hash, n_hash, typ, val)
|
||||
}
|
||||
Instruction::Jump(lbl) => write!(f, "j {}", lbl),
|
||||
Instruction::JumpAndLink(lbl) => write!(f, "jal {}", lbl),
|
||||
Instruction::JumpRelative(off) => write!(f, "jr {}", off),
|
||||
Instruction::BranchEq(a, b, lbl) => write!(f, "beq {} {} {}", a, b, lbl),
|
||||
Instruction::BranchNe(a, b, lbl) => write!(f, "bne {} {} {}", a, b, lbl),
|
||||
Instruction::BranchGt(a, b, lbl) => write!(f, "bgt {} {} {}", a, b, lbl),
|
||||
Instruction::BranchLt(a, b, lbl) => write!(f, "blt {} {} {}", a, b, lbl),
|
||||
Instruction::BranchGe(a, b, lbl) => write!(f, "bge {} {} {}", a, b, lbl),
|
||||
Instruction::BranchLe(a, b, lbl) => write!(f, "ble {} {} {}", a, b, lbl),
|
||||
Instruction::BranchEqZero(a, lbl) => write!(f, "beqz {} {}", a, lbl),
|
||||
Instruction::BranchNeZero(a, lbl) => write!(f, "bnez {} {}", a, lbl),
|
||||
Instruction::SetEq(dst, a, b) => write!(f, "seq {} {} {}", dst, a, b),
|
||||
Instruction::SetNe(dst, a, b) => write!(f, "sne {} {} {}", dst, a, b),
|
||||
Instruction::SetGt(dst, a, b) => write!(f, "sgt {} {} {}", dst, a, b),
|
||||
Instruction::SetLt(dst, a, b) => write!(f, "slt {} {} {}", dst, a, b),
|
||||
Instruction::SetGe(dst, a, b) => write!(f, "sge {} {} {}", dst, a, b),
|
||||
Instruction::SetLe(dst, a, b) => write!(f, "sle {} {} {}", dst, a, b),
|
||||
Instruction::And(dst, a, b) => write!(f, "and {} {} {}", dst, a, b),
|
||||
Instruction::Or(dst, a, b) => write!(f, "or {} {} {}", dst, a, b),
|
||||
Instruction::Xor(dst, a, b) => write!(f, "xor {} {} {}", dst, a, b),
|
||||
Instruction::Push(val) => write!(f, "push {}", val),
|
||||
Instruction::Pop(dst) => write!(f, "pop {}", dst),
|
||||
Instruction::Peek(dst) => write!(f, "peek {}", dst),
|
||||
Instruction::Get(dst, dev, val) => write!(f, "get {} {} {}", dst, dev, val),
|
||||
Instruction::Put(dev, addr, val) => write!(f, "put {} {} {}", dev, addr, val),
|
||||
Instruction::Select(dst, cond, a, b) => {
|
||||
write!(f, "select {} {} {} {}", dst, cond, a, b)
|
||||
}
|
||||
Instruction::Yield => write!(f, "yield"),
|
||||
Instruction::Sleep(val) => write!(f, "sleep {}", val),
|
||||
Instruction::Alias(name, target) => write!(f, "alias {} {}", name, target),
|
||||
Instruction::Define(name, val) => write!(f, "define {} {}", name, val),
|
||||
Instruction::LabelDef(lbl) => write!(f, "{}:", lbl),
|
||||
Instruction::Comment(c) => write!(f, "# {}", c),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user