use lamina_platform::{TargetArchitecture, TargetOperatingSystem};
pub fn is_assembly_emission_supported(arch: TargetArchitecture, os: TargetOperatingSystem) -> bool {
match arch {
TargetArchitecture::Nvptx64 => os == TargetOperatingSystem::Cuda,
TargetArchitecture::Amdgcn => os == TargetOperatingSystem::AmdHsa,
TargetArchitecture::X86_64 => os_supported_for_x86_64(os),
TargetArchitecture::Aarch64 => os_supported_for_aarch64(os),
#[cfg(feature = "nightly")]
TargetArchitecture::Arx64 => os_supported_for_arx64(os),
TargetArchitecture::Riscv32 | TargetArchitecture::Riscv64 => os_supported_for_riscv(os),
TargetArchitecture::LoongArch64 => os == TargetOperatingSystem::Linux,
TargetArchitecture::S390x => os == TargetOperatingSystem::Linux,
TargetArchitecture::Mips64 | TargetArchitecture::Mips64El => {
os == TargetOperatingSystem::Linux
}
TargetArchitecture::I686 => os == TargetOperatingSystem::Linux,
TargetArchitecture::Wasm32 => {
matches!(
os,
TargetOperatingSystem::Unknown
| TargetOperatingSystem::Linux
| TargetOperatingSystem::Wasi
)
}
TargetArchitecture::Wasm64 => {
matches!(
os,
TargetOperatingSystem::Unknown | TargetOperatingSystem::Linux
)
}
TargetArchitecture::Armv7 => os == TargetOperatingSystem::Linux,
TargetArchitecture::Thumbv6m | TargetArchitecture::Thumbv7m => {
matches!(
os,
TargetOperatingSystem::Unknown | TargetOperatingSystem::Linux
)
}
TargetArchitecture::PowerPC64 => {
matches!(
os,
TargetOperatingSystem::Linux | TargetOperatingSystem::Unknown
)
}
TargetArchitecture::PowerPC64Be => os == TargetOperatingSystem::Linux,
TargetArchitecture::Arm32 => false,
#[cfg(feature = "nightly")]
TargetArchitecture::Riscv128 | TargetArchitecture::Lisa => false,
}
}
fn os_supported_for_x86_64(os: TargetOperatingSystem) -> bool {
matches!(
os,
TargetOperatingSystem::Linux
| TargetOperatingSystem::Android
| TargetOperatingSystem::MacOS
| TargetOperatingSystem::IOS
| TargetOperatingSystem::TvOS
| TargetOperatingSystem::WatchOS
| TargetOperatingSystem::VisionOS
| TargetOperatingSystem::Windows
| TargetOperatingSystem::FreeBSD
| TargetOperatingSystem::OpenBSD
| TargetOperatingSystem::NetBSD
| TargetOperatingSystem::DragonFly
| TargetOperatingSystem::Redox
| TargetOperatingSystem::Unknown
)
}
fn os_supported_for_aarch64(os: TargetOperatingSystem) -> bool {
matches!(
os,
TargetOperatingSystem::Linux
| TargetOperatingSystem::Android
| TargetOperatingSystem::MacOS
| TargetOperatingSystem::IOS
| TargetOperatingSystem::TvOS
| TargetOperatingSystem::WatchOS
| TargetOperatingSystem::VisionOS
| TargetOperatingSystem::Windows
| TargetOperatingSystem::FreeBSD
| TargetOperatingSystem::OpenBSD
| TargetOperatingSystem::NetBSD
| TargetOperatingSystem::DragonFly
| TargetOperatingSystem::Redox
| TargetOperatingSystem::Unknown
)
}
#[cfg(feature = "nightly")]
fn os_supported_for_arx64(os: TargetOperatingSystem) -> bool {
matches!(os, TargetOperatingSystem::Unknown)
}
fn os_supported_for_riscv(os: TargetOperatingSystem) -> bool {
matches!(
os,
TargetOperatingSystem::Linux
| TargetOperatingSystem::FreeBSD
| TargetOperatingSystem::OpenBSD
| TargetOperatingSystem::NetBSD
| TargetOperatingSystem::DragonFly
| TargetOperatingSystem::Unknown
)
}
pub fn supported_assembly_targets_hint() -> &'static str {
"Supported: x86_64 and aarch64 on Linux, Android, macOS, iOS, Windows, BSD, Redox and bare metal; \n riscv32/riscv64 on Linux, BSD and bare metal; i686, armv7, ppc64le, ppc64, s390x, mips64, mips64el \n and loongarch64 on Linux; thumbv6m/thumbv7m on Linux and bare metal; wasm32 on Linux, WASI and \n bare metal, wasm64 on Linux and bare metal; nvptx64 on CUDA and amdgcn on AMDHSA. \n Use lamina_platform::Target for cross-compilation."
}
pub fn os_uses_elf(os: TargetOperatingSystem) -> bool {
matches!(
os,
TargetOperatingSystem::Linux
| TargetOperatingSystem::Android
| TargetOperatingSystem::FreeBSD
| TargetOperatingSystem::OpenBSD
| TargetOperatingSystem::NetBSD
| TargetOperatingSystem::DragonFly
| TargetOperatingSystem::Redox
| TargetOperatingSystem::Horizon
| TargetOperatingSystem::Orbis
| TargetOperatingSystem::Prospero
)
}
pub fn os_uses_macho(os: TargetOperatingSystem) -> bool {
matches!(
os,
TargetOperatingSystem::MacOS
| TargetOperatingSystem::IOS
| TargetOperatingSystem::TvOS
| TargetOperatingSystem::WatchOS
| TargetOperatingSystem::VisionOS
)
}
pub fn os_uses_coff(os: TargetOperatingSystem) -> bool {
os == TargetOperatingSystem::Windows
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_x86_64_cross_platform() {
assert!(is_assembly_emission_supported(
TargetArchitecture::X86_64,
TargetOperatingSystem::Linux
));
assert!(is_assembly_emission_supported(
TargetArchitecture::X86_64,
TargetOperatingSystem::Windows
));
assert!(is_assembly_emission_supported(
TargetArchitecture::X86_64,
TargetOperatingSystem::MacOS
));
assert!(is_assembly_emission_supported(
TargetArchitecture::X86_64,
TargetOperatingSystem::FreeBSD
));
}
#[test]
fn test_aarch64_cross_platform() {
assert!(is_assembly_emission_supported(
TargetArchitecture::Aarch64,
TargetOperatingSystem::Linux
));
assert!(is_assembly_emission_supported(
TargetArchitecture::Aarch64,
TargetOperatingSystem::MacOS
));
}
#[test]
fn test_riscv_elf_like_only() {
assert!(is_assembly_emission_supported(
TargetArchitecture::Riscv64,
TargetOperatingSystem::Linux
));
assert!(!is_assembly_emission_supported(
TargetArchitecture::Riscv64,
TargetOperatingSystem::Windows
));
}
#[test]
fn test_wasm_limited_os() {
assert!(is_assembly_emission_supported(
TargetArchitecture::Wasm32,
TargetOperatingSystem::Unknown
));
assert!(is_assembly_emission_supported(
TargetArchitecture::Wasm32,
TargetOperatingSystem::Wasi
));
assert!(!is_assembly_emission_supported(
TargetArchitecture::Wasm64,
TargetOperatingSystem::Wasi
));
assert!(!is_assembly_emission_supported(
TargetArchitecture::X86_64,
TargetOperatingSystem::Wasi
));
}
#[test]
fn test_unknown_os_fallback() {
assert!(is_assembly_emission_supported(
TargetArchitecture::X86_64,
TargetOperatingSystem::Unknown
));
assert!(is_assembly_emission_supported(
TargetArchitecture::Aarch64,
TargetOperatingSystem::Unknown
));
}
#[test]
fn test_apple_mobile_assembly_supported() {
for os in [
TargetOperatingSystem::IOS,
TargetOperatingSystem::TvOS,
TargetOperatingSystem::WatchOS,
TargetOperatingSystem::VisionOS,
] {
assert!(
is_assembly_emission_supported(TargetArchitecture::X86_64, os),
"{os}"
);
assert!(
is_assembly_emission_supported(TargetArchitecture::Aarch64, os),
"{os}"
);
}
}
#[test]
fn test_android_is_elf_and_assembly_supported() {
assert!(is_assembly_emission_supported(
TargetArchitecture::X86_64,
TargetOperatingSystem::Android
));
assert!(is_assembly_emission_supported(
TargetArchitecture::Aarch64,
TargetOperatingSystem::Android
));
assert!(os_uses_elf(TargetOperatingSystem::Android));
}
#[test]
fn test_apple_mobile_oses_use_macho() {
for os in [
TargetOperatingSystem::IOS,
TargetOperatingSystem::TvOS,
TargetOperatingSystem::WatchOS,
TargetOperatingSystem::VisionOS,
] {
assert!(os_uses_macho(os), "{os} should use Mach-O");
assert!(!os_uses_elf(os), "{os} should not use ELF");
}
}
#[test]
fn test_unsupported_arch() {
assert!(!is_assembly_emission_supported(
TargetArchitecture::Arm32,
TargetOperatingSystem::Linux
));
}
#[test]
fn test_powerpc64_assembly_supported() {
assert!(is_assembly_emission_supported(
TargetArchitecture::PowerPC64,
TargetOperatingSystem::Linux
));
assert!(is_assembly_emission_supported(
TargetArchitecture::PowerPC64,
TargetOperatingSystem::Unknown
));
assert!(is_assembly_emission_supported(
TargetArchitecture::PowerPC64Be,
TargetOperatingSystem::Linux
));
assert!(!is_assembly_emission_supported(
TargetArchitecture::PowerPC64Be,
TargetOperatingSystem::Windows
));
}
#[test]
fn test_os_uses_elf() {
assert!(os_uses_elf(TargetOperatingSystem::Linux));
assert!(os_uses_elf(TargetOperatingSystem::FreeBSD));
assert!(os_uses_elf(TargetOperatingSystem::Redox));
assert!(os_uses_elf(TargetOperatingSystem::Horizon));
assert!(os_uses_elf(TargetOperatingSystem::Orbis));
assert!(os_uses_elf(TargetOperatingSystem::Prospero));
assert!(!os_uses_elf(TargetOperatingSystem::MacOS));
assert!(!os_uses_elf(TargetOperatingSystem::Windows));
}
}