Skip to main content

lamina_codegen/
target_support.rs

1//! Cross-platform target support for code generation.
2//!
3//! This module defines which (architecture, OS) combinations are supported
4//! for assembly and binary emission, so callers can cross-compile to a
5//! different target than the host.
6
7use lamina_platform::{TargetArchitecture, TargetOperatingSystem};
8
9/// Returns true if assembly text generation is supported for this (arch, os).
10///
11/// Cross-compilation: pass the desired target, not the host.
12pub fn is_assembly_supported(arch: TargetArchitecture, os: TargetOperatingSystem) -> bool {
13    match arch {
14        TargetArchitecture::X86_64 => os_supported_for_x86_64(os),
15        TargetArchitecture::Aarch64 => os_supported_for_aarch64(os),
16        TargetArchitecture::Arx64 => os_supported_for_arx64(os),
17        TargetArchitecture::Riscv32 | TargetArchitecture::Riscv64 => os_supported_for_riscv(os),
18        TargetArchitecture::Wasm32 | TargetArchitecture::Wasm64 => {
19            matches!(
20                os,
21                TargetOperatingSystem::Unknown | TargetOperatingSystem::Linux
22            )
23        }
24        _ => false,
25    }
26}
27
28/// Returns true if the OS is supported for x86_64 code generation.
29fn os_supported_for_x86_64(os: TargetOperatingSystem) -> bool {
30    matches!(
31        os,
32        TargetOperatingSystem::Linux
33            | TargetOperatingSystem::MacOS
34            | TargetOperatingSystem::Windows
35            | TargetOperatingSystem::FreeBSD
36            | TargetOperatingSystem::OpenBSD
37            | TargetOperatingSystem::NetBSD
38            | TargetOperatingSystem::DragonFly
39            | TargetOperatingSystem::Redox
40            | TargetOperatingSystem::Unknown
41    )
42}
43
44/// Returns true if the OS is supported for AArch64 code generation.
45fn os_supported_for_aarch64(os: TargetOperatingSystem) -> bool {
46    matches!(
47        os,
48        TargetOperatingSystem::Linux
49            | TargetOperatingSystem::MacOS
50            | TargetOperatingSystem::Windows
51            | TargetOperatingSystem::FreeBSD
52            | TargetOperatingSystem::OpenBSD
53            | TargetOperatingSystem::NetBSD
54            | TargetOperatingSystem::DragonFly
55            | TargetOperatingSystem::Redox
56            | TargetOperatingSystem::Unknown
57    )
58}
59
60/// Returns true if the OS is supported for ARX64 code generation.
61fn os_supported_for_arx64(os: TargetOperatingSystem) -> bool {
62    matches!(os, TargetOperatingSystem::Unknown)
63}
64
65/// Returns true if the OS is supported for RISC-V code generation.
66fn os_supported_for_riscv(os: TargetOperatingSystem) -> bool {
67    matches!(
68        os,
69        TargetOperatingSystem::Linux
70            | TargetOperatingSystem::FreeBSD
71            | TargetOperatingSystem::OpenBSD
72            | TargetOperatingSystem::NetBSD
73            | TargetOperatingSystem::DragonFly
74            | TargetOperatingSystem::Unknown
75    )
76}
77
78/// Returns a short description of supported targets for error messages.
79pub fn supported_assembly_targets_hint() -> &'static str {
80    "Supported: x86_64/aarch64/riscv32/riscv64/wasm32 on Linux, macOS, Windows, BSD, Redox \n and for bare-metal. Use lamina_platform::Target for cross-compilation."
81}
82
83/// Returns true if the given OS uses ELF object format (Linux, BSD, Redox).
84pub fn os_uses_elf(os: TargetOperatingSystem) -> bool {
85    matches!(
86        os,
87        TargetOperatingSystem::Linux
88            | TargetOperatingSystem::FreeBSD
89            | TargetOperatingSystem::OpenBSD
90            | TargetOperatingSystem::NetBSD
91            | TargetOperatingSystem::DragonFly
92            | TargetOperatingSystem::Redox
93    )
94}
95
96/// Returns true if the given OS uses Mach-O (macOS).
97pub fn os_uses_macho(os: TargetOperatingSystem) -> bool {
98    os == TargetOperatingSystem::MacOS
99}
100
101/// Returns true if the given OS uses COFF/PE (Windows).
102pub fn os_uses_coff(os: TargetOperatingSystem) -> bool {
103    os == TargetOperatingSystem::Windows
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109
110    #[test]
111    fn test_x86_64_cross_platform() {
112        assert!(is_assembly_supported(
113            TargetArchitecture::X86_64,
114            TargetOperatingSystem::Linux
115        ));
116        assert!(is_assembly_supported(
117            TargetArchitecture::X86_64,
118            TargetOperatingSystem::Windows
119        ));
120        assert!(is_assembly_supported(
121            TargetArchitecture::X86_64,
122            TargetOperatingSystem::MacOS
123        ));
124        assert!(is_assembly_supported(
125            TargetArchitecture::X86_64,
126            TargetOperatingSystem::FreeBSD
127        ));
128    }
129
130    #[test]
131    fn test_aarch64_cross_platform() {
132        assert!(is_assembly_supported(
133            TargetArchitecture::Aarch64,
134            TargetOperatingSystem::Linux
135        ));
136        assert!(is_assembly_supported(
137            TargetArchitecture::Aarch64,
138            TargetOperatingSystem::MacOS
139        ));
140    }
141
142    #[test]
143    fn test_riscv_elf_like_only() {
144        assert!(is_assembly_supported(
145            TargetArchitecture::Riscv64,
146            TargetOperatingSystem::Linux
147        ));
148        assert!(!is_assembly_supported(
149            TargetArchitecture::Riscv64,
150            TargetOperatingSystem::Windows
151        ));
152    }
153
154    #[test]
155    fn test_wasm_limited_os() {
156        assert!(is_assembly_supported(
157            TargetArchitecture::Wasm32,
158            TargetOperatingSystem::Unknown
159        ));
160    }
161
162    #[test]
163    fn test_unknown_os_fallback() {
164        assert!(is_assembly_supported(
165            TargetArchitecture::X86_64,
166            TargetOperatingSystem::Unknown
167        ));
168        assert!(is_assembly_supported(
169            TargetArchitecture::Aarch64,
170            TargetOperatingSystem::Unknown
171        ));
172    }
173
174    #[test]
175    fn test_unsupported_arch() {
176        assert!(!is_assembly_supported(
177            TargetArchitecture::Unknown,
178            TargetOperatingSystem::Linux
179        ));
180    }
181
182    #[test]
183    fn test_os_uses_elf() {
184        assert!(os_uses_elf(TargetOperatingSystem::Linux));
185        assert!(os_uses_elf(TargetOperatingSystem::FreeBSD));
186        assert!(os_uses_elf(TargetOperatingSystem::Redox));
187        assert!(!os_uses_elf(TargetOperatingSystem::MacOS));
188        assert!(!os_uses_elf(TargetOperatingSystem::Windows));
189    }
190}