Skip to main content

lamina_codegen/powerpc/
abi.rs

1//! PowerPC64 ELFv2 ABI (Linux ppc64le).
2//!
3//! ## Calling Convention Summary
4//!
5//! - Integer arguments: r3–r10 (8 registers). Overflow args go on the stack.
6//! - Integer return value: r3.
7//! - Float arguments: f1–f13. Float return value: f1.
8//! - Caller-saved: r0, r3–r12, f0–f13, lr.
9//! - Callee-saved: r14–r31, f14–f31, cr2–cr4.
10//! - Stack pointer: r1 (must be 16-byte aligned at call sites).
11//! - TOC pointer: r2 (do not clobber).
12
13use crate::abi::{Abi, common_call_stub, mangle_macos_name};
14use lamina_platform::TargetOperatingSystem;
15
16pub struct Ppc64Abi {
17    target_os: TargetOperatingSystem,
18}
19
20impl Ppc64Abi {
21    pub fn new(target_os: TargetOperatingSystem) -> Self {
22        Self { target_os }
23    }
24
25    pub fn mangle_function_name(&self, name: &str) -> String {
26        match self.target_os {
27            TargetOperatingSystem::MacOS => mangle_macos_name(name),
28            _ => name.to_string(),
29        }
30    }
31
32    pub fn get_main_global(&self) -> &'static str {
33        ".globl main"
34    }
35
36    pub fn get_data_section(&self) -> &'static str {
37        ".data"
38    }
39
40    pub fn get_text_section(&self) -> &'static str {
41        ".text"
42    }
43
44    pub const ARG_REGISTERS: &'static [&'static str] = &["3", "4", "5", "6", "7", "8", "9", "10"];
45
46    pub fn call_stub(&self, name: &str) -> Option<String> {
47        common_call_stub(name, self.target_os)
48    }
49}
50
51impl Abi for Ppc64Abi {
52    fn target_os(&self) -> TargetOperatingSystem {
53        self.target_os
54    }
55
56    fn mangle_function_name(&self, name: &str) -> String {
57        Ppc64Abi::mangle_function_name(self, name)
58    }
59
60    fn call_stub(&self, name: &str) -> Option<String> {
61        Ppc64Abi::call_stub(self, name)
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn test_ppc64_mangle_linux() {
71        let abi = Ppc64Abi::new(TargetOperatingSystem::Linux);
72        assert_eq!(abi.mangle_function_name("main"), "main");
73        assert_eq!(abi.mangle_function_name("foo"), "foo");
74    }
75
76    #[test]
77    fn test_ppc64_call_stub_linux() {
78        let abi = Ppc64Abi::new(TargetOperatingSystem::Linux);
79        assert_eq!(abi.call_stub("malloc"), Some("malloc".to_string()));
80        assert_eq!(abi.call_stub("unknown"), None);
81    }
82
83    #[test]
84    fn test_ppc64_arg_registers() {
85        assert_eq!(Ppc64Abi::ARG_REGISTERS.len(), 8);
86        assert_eq!(Ppc64Abi::ARG_REGISTERS[0], "3");
87    }
88}