lamina_codegen/x86_64/
abi.rs1use crate::abi::{Abi, common_call_stub, mangle_macos_name};
4use crate::target_support::os_uses_macho;
5use lamina_platform::TargetOperatingSystem;
6
7pub struct X86ABI {
9 target_os: TargetOperatingSystem,
10}
11
12impl X86ABI {
13 pub fn new(target_os: TargetOperatingSystem) -> Self {
15 Self { target_os }
16 }
17
18 pub fn mangle_function_name(&self, name: &str) -> String {
20 match self.target_os {
21 os if os_uses_macho(os) => mangle_macos_name(name),
22 TargetOperatingSystem::Windows => {
23 if name == "main" {
24 "main".to_string()
25 } else {
26 name.to_string()
27 }
28 }
29 _ => name.to_string(),
30 }
31 }
32
33 pub fn get_main_global(&self) -> &'static str {
35 ".globl main"
36 }
37
38 pub fn arg_registers(&self) -> &'static [&'static str] {
43 match self.target_os {
44 TargetOperatingSystem::Windows => &["rcx", "rdx", "r8", "r9"],
45 _ => &["rdi", "rsi", "rdx", "rcx", "r8", "r9"],
46 }
47 }
48
49 pub const ARG_REGISTERS: &'static [&'static str] = &["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
53
54 pub const CALLER_SAVED_REGISTERS: &'static [&'static str] =
56 &["rax", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11"];
57
58 pub const CALLEE_SAVED_REGISTERS: &'static [&'static str] =
60 &["rbx", "rbp", "r12", "r13", "r14", "r15"];
61}
62
63impl Abi for X86ABI {
64 fn target_os(&self) -> TargetOperatingSystem {
65 self.target_os
66 }
67
68 fn mangle_function_name(&self, name: &str) -> String {
69 X86ABI::mangle_function_name(self, name)
70 }
71
72 fn call_stub(&self, name: &str) -> Option<String> {
73 common_call_stub(name, self.target_os)
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_x86_mangle_function_name() {
83 let abi_linux = X86ABI::new(TargetOperatingSystem::Linux);
84 assert_eq!(abi_linux.mangle_function_name("main"), "main");
85 assert_eq!(abi_linux.mangle_function_name("foo"), "foo");
86
87 let abi_macos = X86ABI::new(TargetOperatingSystem::MacOS);
88 assert_eq!(abi_macos.mangle_function_name("main"), "_main");
89 assert_eq!(abi_macos.mangle_function_name("foo"), "_foo");
90
91 let abi_ios = X86ABI::new(TargetOperatingSystem::IOS);
92 assert_eq!(abi_ios.mangle_function_name("main"), "_main");
93 assert_eq!(abi_ios.mangle_function_name("foo"), "_foo");
94
95 let abi_windows = X86ABI::new(TargetOperatingSystem::Windows);
96 assert_eq!(abi_windows.mangle_function_name("main"), "main");
97 assert_eq!(abi_windows.mangle_function_name("foo"), "foo");
98 }
99
100 #[test]
101 fn test_x86_call_stub() {
102 let abi_linux = X86ABI::new(TargetOperatingSystem::Linux);
103 assert_eq!(abi_linux.call_stub("malloc"), Some("malloc".to_string()));
104 assert_eq!(abi_linux.call_stub("dealloc"), Some("free".to_string()));
105 assert_eq!(abi_linux.call_stub("unknown"), None);
106
107 let abi_macos = X86ABI::new(TargetOperatingSystem::MacOS);
108 assert_eq!(abi_macos.call_stub("malloc"), Some("_malloc".to_string()));
109 }
110
111 #[test]
112 fn test_x86_arg_registers() {
113 let abi_linux = X86ABI::new(TargetOperatingSystem::Linux);
114 let regs = abi_linux.arg_registers();
115 assert_eq!(regs.len(), 6);
116 assert_eq!(regs[0], "rdi");
117 assert_eq!(regs[1], "rsi");
118 assert_eq!(regs[2], "rdx");
119 assert_eq!(regs[3], "rcx");
120 assert_eq!(regs[4], "r8");
121 assert_eq!(regs[5], "r9");
122
123 let abi_windows = X86ABI::new(TargetOperatingSystem::Windows);
124 let regs_win = abi_windows.arg_registers();
125 assert_eq!(regs_win.len(), 4);
126 assert_eq!(regs_win[0], "rcx");
127 assert_eq!(regs_win[1], "rdx");
128 assert_eq!(regs_win[2], "r8");
129 assert_eq!(regs_win[3], "r9");
130 }
131
132 #[test]
133 fn test_x86_caller_saved_registers() {
134 assert_eq!(X86ABI::CALLER_SAVED_REGISTERS.len(), 9);
135 assert!(X86ABI::CALLER_SAVED_REGISTERS.contains(&"rax"));
136 assert!(X86ABI::CALLER_SAVED_REGISTERS.contains(&"rdi"));
137 }
138
139 #[test]
140 fn test_x86_callee_saved_registers() {
141 assert_eq!(X86ABI::CALLEE_SAVED_REGISTERS.len(), 6);
142 assert!(X86ABI::CALLEE_SAVED_REGISTERS.contains(&"rbx"));
143 assert!(X86ABI::CALLEE_SAVED_REGISTERS.contains(&"rbp"));
144 }
145}