Skip to main content

lamina_codegen/x86_64/
abi.rs

1//! x86_64 ABI utilities for different platforms.
2
3use crate::abi::{Abi, common_call_stub, mangle_macos_name};
4use lamina_platform::TargetOperatingSystem;
5
6/// Platform-specific ABI utilities for x86_64 code generation.
7pub struct X86ABI {
8    target_os: TargetOperatingSystem,
9}
10
11impl X86ABI {
12    /// Creates a new ABI instance for the specified target OS.
13    pub fn new(target_os: TargetOperatingSystem) -> Self {
14        Self { target_os }
15    }
16
17    /// Returns the mangled function name with platform-specific prefix.
18    pub fn mangle_function_name(&self, name: &str) -> String {
19        match self.target_os {
20            TargetOperatingSystem::MacOS => mangle_macos_name(name),
21            TargetOperatingSystem::Windows => {
22                if name == "main" {
23                    "main".to_string()
24                } else {
25                    name.to_string()
26                }
27            }
28            _ => name.to_string(),
29        }
30    }
31
32    /// Returns the global declaration directive for the main function.
33    pub fn get_main_global(&self) -> &'static str {
34        match self.target_os {
35            TargetOperatingSystem::Windows => ".globl main",
36            _ => ".globl main",
37        }
38    }
39
40    /// Returns the argument registers for the target OS ABI.
41    ///
42    /// - Windows x64: rcx, rdx, r8, r9 (first 4 arguments)
43    /// - System V AMD64: rdi, rsi, rdx, rcx, r8, r9 (first 6 arguments)
44    pub fn arg_registers(&self) -> &'static [&'static str] {
45        match self.target_os {
46            TargetOperatingSystem::Windows => &["rcx", "rdx", "r8", "r9"],
47            _ => &["rdi", "rsi", "rdx", "rcx", "r8", "r9"],
48        }
49    }
50
51    /// System V AMD64 ABI argument registers.
52    ///
53    /// Deprecated: use `arg_registers()` instead for platform-aware register selection.
54    pub const ARG_REGISTERS: &'static [&'static str] = &["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
55
56    /// Caller-saved registers that must be preserved by the caller if live across function calls.
57    pub const CALLER_SAVED_REGISTERS: &'static [&'static str] =
58        &["rax", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11"];
59
60    /// Callee-saved registers that are preserved by called functions.
61    pub const CALLEE_SAVED_REGISTERS: &'static [&'static str] =
62        &["rbx", "rbp", "r12", "r13", "r14", "r15"];
63}
64
65impl Abi for X86ABI {
66    fn target_os(&self) -> TargetOperatingSystem {
67        self.target_os
68    }
69
70    fn mangle_function_name(&self, name: &str) -> String {
71        X86ABI::mangle_function_name(self, name)
72    }
73
74    fn call_stub(&self, name: &str) -> Option<String> {
75        common_call_stub(name, self.target_os)
76    }
77}