]> Witch of Git - ivy/blob - src/trans/x64.rs
Add skeleton of x64 compilation code
[ivy] / src / trans / x64.rs
1 use crate::trans::{FnName, Func, Program};
2 use std::{
3 fmt,
4 io::{self, Write},
5 };
6
7 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8 pub enum Label {
9 Global(u32),
10 Function(FnName),
11 }
12
13 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14 pub enum Addr {
15 Rip(Label),
16 Off(Reg, u32),
17 }
18
19 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20 pub enum Reg {
21 Rax,
22 Rbx,
23 Rcx,
24 Rdx,
25 Rsi,
26 Rdi,
27 Rbp,
28 Rsp,
29 R8,
30 R9,
31 R10,
32 R11,
33 R12,
34 R13,
35 R14,
36 R15,
37 }
38
39 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
40 pub enum Inst {
41 Push(Reg),
42 Load(Reg, Addr),
43 Store(Addr, Reg),
44 Mov(Reg, Reg),
45 Pop(Reg),
46 Ret,
47 }
48
49 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
50 pub struct Definition {
51 name: Label,
52 body: Vec<Inst>,
53 }
54
55 pub struct Global {
56 name: Label,
57 value: i64,
58 }
59
60 pub fn write_compile(out: &mut impl Write, prog: &Program) -> io::Result<()> {
61 let (entry, globals, defns) = compile(&prog);
62 writeln!(out, ".data")?;
63 for global in globals {
64 writeln!(out, "{}", global)?;
65 }
66 writeln!(out)?;
67 writeln!(
68 out,
69 r#".text
70 .global _start
71 _start:
72 sub rsp, 15
73 and spl, 0xF0
74 call {}
75 mov rdi, 0
76 call _ivy_exit
77 "#,
78 entry
79 )?;
80 for defn in defns {
81 writeln!(out, "{}", defn)?;
82 }
83 Ok(())
84 }
85
86 pub fn compile(prog: &Program) -> (Label, Vec<Global>, Vec<Definition>) {
87 let globals = prog
88 .globals
89 .iter()
90 .map(|&global| Global {
91 name: Label::Global(global),
92 value: 0,
93 })
94 .collect();
95 let defns = prog
96 .functions
97 .values()
98 .map(|func| compile_func(prog, func))
99 .collect();
100 (Label::Function(prog.top), globals, defns)
101 }
102
103 fn compile_func(prog: &Program, func: &Func) -> Definition {
104 let mut body = Vec::new();
105 body.push(Inst::Ret);
106 Definition {
107 name: Label::Function(func.name),
108 body,
109 }
110 }
111
112 impl fmt::Display for Definition {
113 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
114 match self.body.len() {
115 0 => write!(fmt, "{}:", self.name),
116 1 => write!(fmt, "{}: {}", self.name, self.body[0]),
117 len => {
118 writeln!(fmt, "{}:", self.name)?;
119 for inst in &self.body[..len - 1] {
120 writeln!(fmt, " {}", inst)?;
121 }
122 write!(fmt, " {}", self.body.last().unwrap())
123 }
124 }
125 }
126 }
127
128 impl fmt::Display for Global {
129 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
130 write!(fmt, "{}: .quad {}", self.name, self.value)
131 }
132 }
133
134 impl fmt::Display for Label {
135 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
136 match self {
137 Label::Global(g) => write!(fmt, "IVY_GLOBAL${}", g),
138 Label::Function(f) => write!(fmt, "ivy_fn${}", f.0),
139 }
140 }
141 }
142
143 impl fmt::Display for Reg {
144 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
145 match self {
146 Reg::Rax => write!(fmt, "rax"),
147 Reg::Rbx => write!(fmt, "rbx"),
148 Reg::Rcx => write!(fmt, "rcx"),
149 Reg::Rdx => write!(fmt, "rdx"),
150 Reg::Rsi => write!(fmt, "rsi"),
151 Reg::Rdi => write!(fmt, "rdi"),
152 Reg::Rbp => write!(fmt, "rbp"),
153 Reg::Rsp => write!(fmt, "rsp"),
154 Reg::R8 => write!(fmt, "r8"),
155 Reg::R9 => write!(fmt, "r9"),
156 Reg::R10 => write!(fmt, "r10"),
157 Reg::R11 => write!(fmt, "r11"),
158 Reg::R12 => write!(fmt, "r12"),
159 Reg::R13 => write!(fmt, "r13"),
160 Reg::R14 => write!(fmt, "r14"),
161 Reg::R15 => write!(fmt, "r15"),
162 }
163 }
164 }
165
166 impl fmt::Display for Inst {
167 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
168 match self {
169 Inst::Push(r) => write!(fmt, "push {}", r),
170 Inst::Pop(r) => write!(fmt, "pop {}", r),
171 Inst::Ret => write!(fmt, "ret"),
172 inst => write!(fmt, "{:?}", inst),
173 }
174 }
175 }