use crate::{
compiler::{emit::eval, state::State},
core::Expr,
immediate,
x86::{self, Reference::*, Register::*, ASM, WORDSIZE},
};
pub fn call(s: &mut State, name: &str, args: &[Expr]) -> ASM {
let mut asm = ASM(vec![]);
if args.len() > 6 {
panic!("foreign function {} called with more than 6 arguments: {:?}", &name, args)
}
for (i, arg) in args.iter().enumerate() {
let target = x86::SYS_V[i];
asm += match immediate::to(arg) {
Some(c) => x86::mov(Register(target), Const(c)).into(),
None => eval(s, &arg) + x86::mov(Register(target), Register(RAX)),
}
}
#[cfg(target_os = "linux")]
fn rename(name: &str) -> String {
name.replace("-", "_").replace("=?", "_eq")
}
#[cfg(target_os = "macos")]
fn rename(name: &str) -> String {
format!("_{}", name.replace("-", "_").replace("=?", "_eq"))
}
let name = rename(name);
if s.si != -WORDSIZE {
asm += x86::sub(RSP.into(), Const(-s.si));
asm += x86::call(&name);
asm += x86::add(RSP.into(), Const(-s.si));
} else {
asm += x86::call(&name)
}
asm
}