use backend_lang::mir::{Effects, Function, Mem, Operand};
use backend_lang::x86_64::{self, RAX, RCX, RDI, RDX, SYSV, op};
use isa_lang::x86_64::{Cond, disassemble};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut f = Function::new("sum", &SYSV);
f.omit_frame_pointer();
let (entry, head, exit) = (f.block()?, f.block()?, f.block()?);
f.add_param(entry, RDI.into())?;
f.add_param(head, RAX.into())?; f.add_param(head, RCX.into())?; f.add_param(exit, RAX.into())?;
let start = f.block_call(head, &[Operand::Imm(0), RDI.into()])?;
f.push(entry, op::JMP, &[start.into()])?;
f.push(
head,
op::LEA64,
&[
RDX.into(),
Mem::base(RAX.into())
.with_index(RCX.into(), backend_lang::mir::Scale::X1)
.into(),
],
)?;
f.push(
head,
op::LEA64,
&[RAX.into(), Mem::base(RCX.into()).with_disp(-1).into()],
)?;
f.push(head, op::MOV64, &[RCX.into(), RDX.into()])?;
f.push(head, op::CMP64, &[RAX.into(), Operand::Imm(0)])?;
let again = f.block_call(head, &[RCX.into(), RAX.into()])?;
let done = f.block_call(exit, &[RCX.into()])?;
f.push(
head,
op::JCC,
&[x86_64::cond(Cond::Ne).into(), again.into(), done.into()],
)?;
f.push_with(exit, op::RET, &[], Effects::new().uses(&[RAX]))?;
f.verify()?;
print!("{f}");
let code = backend_lang::emit(&f)?;
println!("\n{} bytes of x86-64:", code.len());
print!("{}", disassemble(&code, 0));
Ok(())
}