use std::io::Write;
use crate::{reg::Label, traits::Writable};
pub mod expr;
#[allow(missing_docs)]
pub enum LocOptions {
BasicBloc,
PrologueEnd,
EpilogueBegin,
IsStmt(bool),
Isa(usize),
}
impl Writable for LocOptions {
fn write_in(&self, file: &mut std::fs::File) -> std::io::Result<()> {
match self {
Self::BasicBloc => file.write_all(b"basic_block"),
Self::PrologueEnd => file.write_all(b"prologue_end"),
Self::EpilogueBegin => file.write_all(b"epilogue_begin"),
Self::IsStmt(b) => {
file.write_all(format!("is_smt {}", if *b { 1 } else { 0 }).as_bytes())
}
Self::Isa(i) => file.write_all(format!("isa {}", i).as_bytes()),
}
}
}
pub enum Directive {
P2Align(usize, Option<usize>, Option<usize>),
File(usize, String),
Loc(usize, usize, Option<usize>, Vec<LocOptions>),
LocMarkBlocks(bool),
Set(Label, expr::Expr),
}
impl Writable for Directive {
fn write_in(&self, file: &mut std::fs::File) -> std::io::Result<()> {
match self {
Directive::P2Align(i1, opt1, opt2) => {
file.write_all(format!(".p2align {:#x}", i1).as_bytes())?;
if opt1.is_some() || opt2.is_some() {
file.write_all(b",")?;
}
if let Some(i) = opt1 {
file.write_all(format!("{}", i).as_bytes())?;
}
if let Some(i) = opt2 {
file.write_all(format!(",{}", i).as_bytes())?;
}
}
Directive::File(id, name) => {
file.write_all(format!(".file {} \"", id).as_bytes())?;
file.write_all(name.as_bytes())?;
file.write_all(b"\"")?;
}
Directive::Loc(file_id, line, column, options) => {
file.write_all(format!(".loc {} {}", file_id, line).as_bytes())?;
if let Some(i) = column {
file.write_all(format!(" {}", i).as_bytes())?;
}
for opt in options {
file.write_all(b" ")?;
opt.write_in(file)?;
}
}
Directive::LocMarkBlocks(b) => {
file.write_all(format!(".loc_mark_blocks {}", if *b { 1 } else { 0 }).as_bytes())?;
}
Directive::Set(lab, expr) => {
file.write_all(b".set ")?;
lab.write_in(file)?;
file.write_all(b", ")?;
expr.write_in(file)?;
}
}
std::io::Result::Ok(())
}
}
pub fn set_sub(lab1: Label, lab2: Label, lab3: Label) -> Directive {
Directive::Set(lab1, expr::Expr::Sub(lab2, lab3))
}