]>
Witch of Git - ivy/blob - src/trans/x64.rs
   2 use crate::trans
::{Code
, FnName
, Func
, Program
, SsaName
, Var
}; 
  10 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 
  15     Builtin(&'
static str), 
  18 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 
  24 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 
  45 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 
  61 #[derive(Debug, Clone, PartialEq, Eq, Hash)] 
  62 pub struct Definition 
{ 
  64     body
: Cow
<'
static, [Inst
]>, 
  73     builtins
: &HashMap
<String
, ast
::Name
>, 
  77     let (entry
, globals
, defns
) = compile(&prog
); 
  83     let builtins 
= builtins
 
  86             let number 
= id
.global_number().unwrap(); 
  87             let (params
, name
, code
) = builtin(&name
); 
  91                     name
: Label
::Builtin(name
), 
  92                     body
: Cow
::Borrowed(code
), 
  98     writeln!(out
, ".data")?
; 
  99     for global 
in globals 
{ 
 100         writeln!(out
, "{}", global
)?
; 
 112     for builtin 
in &builtins 
{ 
 120     mov [rip + {}], rax"#, 
 123             Label
::Global(builtin
.number
), 
 136     for builtin 
in &builtins 
{ 
 137         writeln!(out
, "{}", builtin
.defn
)?
; 
 141         writeln!(out
, "{}", defn
)?
; 
 147 pub fn compile(prog
: &Program
) -> (Label
, Vec
<Global
>, Vec
<Definition
>) { 
 151         .map(|&global
| Global 
{ 
 152             name
: Label
::Global(global
), 
 159         .map(|func
| compile_func(func
)) 
 161     (Label
::Function(prog
.top
), globals
, defns
) 
 164 fn even_up(x
: usize) -> usize { 
 168 fn compile_func(func
: &Func
) -> Definition 
{ 
 169     fn stack(x
: &SsaName
) -> Addr 
{ 
 170         Addr
::Off(Reg
::Rsp
, x
.0 as i32 * 8) 
 173     const HEADER_SIZE
: i32 = 0x18; 
 175     fn param(x
: u16) -> Addr 
{ 
 176         Addr
::Off(Reg
::Rbx
, HEADER_SIZE 
+ x 
as i32 * 8) 
 179     let upvar 
= move |x
: u16| { 
 180         let params 
= func
.params 
as i32 * 8; 
 181         Addr
::Off(Reg
::Rbx
, HEADER_SIZE 
+ params 
+ x 
as i32 * 8) 
 184     let mut body 
= Vec
::new(); 
 185     let stack_slots 
= even_up(func
.order
.len()); 
 186     body
.push(Inst
::Push(Reg
::Rbx
)); 
 187     body
.push(Inst
::Mov(Reg
::Rbx
, Reg
::Rdi
)); 
 188     body
.push(Inst
::Sub(Reg
::Rsp
, stack_slots 
as u32 * 8)); 
 189     for ssa 
in &func
.order 
{ 
 190         match &func
.block
[ssa
] { 
 191             Code
::Load(Var
::Global(x
)) => { 
 192                 body
.push(Inst
::Load(Reg
::Rax
, Addr
::Rip(Label
::Global(*x
)))); 
 193                 body
.push(Inst
::Store(stack(ssa
), Reg
::Rax
)); 
 195             Code
::Load(Var
::Param(x
)) => { 
 196                 body
.push(Inst
::Load(Reg
::Rax
, param(*x
))); 
 197                 body
.push(Inst
::Store(stack(ssa
), Reg
::Rax
)); 
 199             Code
::Load(Var
::Upvar(x
)) => { 
 200                 body
.push(Inst
::Load(Reg
::Rax
, upvar(*x
))); 
 201                 body
.push(Inst
::Store(stack(ssa
), Reg
::Rax
)); 
 203             Code
::Load(Var
::Ssa(ssa2
)) => { 
 204                 body
.push(Inst
::Load(Reg
::Rax
, stack(ssa2
))); 
 205                 body
.push(Inst
::Store(stack(ssa
), Reg
::Rax
)); 
 207             Code
::StoreGlobal(x
, s
) => { 
 208                 body
.push(Inst
::Load(Reg
::Rax
, stack(s
))); 
 209                 body
.push(Inst
::Store(Addr
::Rip(Label
::Global(*x
)), Reg
::Rax
)); 
 216                 body
.push(Inst
::Lea(Reg
::Rdi
, Addr
::Rip(Label
::Function(*name
)))); 
 217                 body
.push(Inst
::Imm(Reg
::Rsi
, *params 
as i64)); 
 218                 body
.push(Inst
::Imm(Reg
::Rdx
, upvars
.len() as i64)); 
 219                 body
.push(Inst
::Call(Label
::Extern("_ivy_make_lam"))); 
 220                 // @TODO: Implement copying in closure captures 
 221                 assert!(upvars
.is_empty()); 
 222                 body
.push(Inst
::Store(stack(ssa
), Reg
::Rax
)); 
 224             Code
::App(terms
) => { 
 225                 let mut terms 
= terms
.iter(); 
 226                 body
.push(Inst
::Load( 
 228                     stack(terms
.next().expect("a function to apply")), 
 231                     Some(s
) => body
.push(Inst
::Load(Reg
::Rsi
, stack(s
))), 
 232                     None 
=> body
.push(Inst
::Imm(Reg
::Rsi
, 0)), 
 234                 body
.push(Inst
::Call(Label
::Extern("_ivy_app"))); 
 235                 while let Some(term
) = terms
.next() { 
 236                     body
.push(Inst
::Mov(Reg
::Rdi
, Reg
::Rax
)); 
 237                     body
.push(Inst
::Load(Reg
::Rsi
, stack(term
))); 
 238                     body
.push(Inst
::Call(Label
::Extern("_ivy_app_mut"))); 
 240                 body
.push(Inst
::Store(stack(ssa
), Reg
::Rax
)); 
 243                 body
.push(Inst
::Imm(Reg
::Rax
, (n 
<< 1) | 1i64)); 
 244                 body
.push(Inst
::Store(stack(ssa
), Reg
::Rax
)); 
 248     body
.push(Inst
::Add(Reg
::Rsp
, stack_slots 
as u32 * 8)); 
 249     body
.push(Inst
::Pop(Reg
::Rbx
)); 
 250     body
.push(Inst
::Ret
); 
 252         name
: Label
::Function(func
.name
), 
 253         body
: Cow
::Owned(body
), 
 257 impl fmt
::Display 
for Definition 
{ 
 258     fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result 
{ 
 259         match self.body
.len() { 
 260             0 => write!(fmt
, "{}:", self.name
), 
 261             1 => write!(fmt
, "{}: {}", self.name
, self.body
[0]), 
 263                 writeln!(fmt
, "{}:", self.name
)?
; 
 264                 for inst 
in &self.body
[..len 
- 1] { 
 265                     writeln!(fmt
, "    {}", inst
)?
; 
 267                 write!(fmt
, "    {}", self.body
.last().unwrap()) 
 273 impl fmt
::Display 
for Global 
{ 
 274     fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result 
{ 
 275         write!(fmt
, "{}: .quad {}", self.name
, self.value
) 
 279 impl fmt
::Display 
for Label 
{ 
 280     fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result 
{ 
 282             Label
::Global(g
) => write!(fmt
, "IVY_GLOBAL${}", g
), 
 283             Label
::Function(f
) => write!(fmt
, "ivy_fn${}", f
.0), 
 284             Label
::Extern(l
) => write!(fmt
, "{}", l
), 
 285             Label
::Builtin(l
) => write!(fmt
, "ivy_builtin${}", l
), 
 290 impl fmt
::Display 
for Reg 
{ 
 291     fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result 
{ 
 293             Reg
::Rax 
=> write!(fmt
, "rax"), 
 294             Reg
::Rbx 
=> write!(fmt
, "rbx"), 
 295             Reg
::Rcx 
=> write!(fmt
, "rcx"), 
 296             Reg
::Rdx 
=> write!(fmt
, "rdx"), 
 297             Reg
::Rsi 
=> write!(fmt
, "rsi"), 
 298             Reg
::Rdi 
=> write!(fmt
, "rdi"), 
 299             Reg
::Rbp 
=> write!(fmt
, "rbp"), 
 300             Reg
::Rsp 
=> write!(fmt
, "rsp"), 
 301             Reg
::R8 
=> write!(fmt
, "r8"), 
 302             Reg
::R9 
=> write!(fmt
, "r9"), 
 303             Reg
::R10 
=> write!(fmt
, "r10"), 
 304             Reg
::R11 
=> write!(fmt
, "r11"), 
 305             Reg
::R12 
=> write!(fmt
, "r12"), 
 306             Reg
::R13 
=> write!(fmt
, "r13"), 
 307             Reg
::R14 
=> write!(fmt
, "r14"), 
 308             Reg
::R15 
=> write!(fmt
, "r15"), 
 313 impl fmt
::Display 
for Addr 
{ 
 314     fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result 
{ 
 316             Addr
::Rip(l
) => write!(fmt
, "[rip + {}]", l
), 
 317             Addr
::Off(r
, o
) => write!(fmt
, "[{} + {}]", r
, o
), 
 322 impl fmt
::Display 
for Inst 
{ 
 323     fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result 
{ 
 325             Inst
::Push(r
) => write!(fmt
, "push {}", r
), 
 326             Inst
::Pop(r
) => write!(fmt
, "pop {}", r
), 
 327             Inst
::Mov(d
, s
) => write!(fmt
, "mov {}, {}", d
, s
), 
 328             Inst
::Load(r
, a
) => write!(fmt
, "mov {}, {}", r
, a
), 
 329             Inst
::Store(a
, r
) => write!(fmt
, "mov {}, {}", a
, r
), 
 330             Inst
::Imm(r
, i
) => write!(fmt
, "mov {}, {}", r
, i
), 
 331             Inst
::Lea(r
, a
) => write!(fmt
, "lea {}, {}", r
, a
), 
 332             Inst
::Call(l
) => write!(fmt
, "call {}", l
), 
 333             Inst
::Jmp(l
) => write!(fmt
, "jmp {}", l
), 
 334             Inst
::Add(r
, x
) => write!(fmt
, "add {}, {}", r
, x
), 
 335             Inst
::Sub(r
, x
) => write!(fmt
, "sub {}, {}", r
, x
), 
 336             Inst
::Ret 
=> write!(fmt
, "ret"), 
 341 fn builtin(name
: &str) -> (u16, &'
static str, &'
static [Inst
]) { 
 347                 Inst
::Load(Reg
::Rdi
, Addr
::Off(Reg
::Rdi
, 0x18)), 
 348                 Inst
::Jmp(Label
::Extern("_ivy_debug")), 
 351         name 
=> panic!("Unsupported builtin '{}' for x64", name
), 
 
This page took 0.067243 seconds  and 5 git commands  to generate.