use core::fmt;
use crate::{Arch, DataModel, Env, Os, SubArch};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum Abi {
#[default]
Default,
SoftFloat,
SoftFp,
SingleFloat,
DoubleFloat,
}
impl Abi {
pub const fn as_str(self) -> &'static str {
match self {
Abi::Default => "default",
Abi::SoftFloat => "soft",
Abi::SoftFp => "softfp",
Abi::SingleFloat => "single",
Abi::DoubleFloat => "hard",
}
}
pub const fn resolve(self, arch: Arch, sub_arch: SubArch, os: Os, env: Env) -> Abi {
if !matches!(self, Abi::Default) {
return self;
}
match arch {
Arch::Arm => {
if sub_arch.is_thumb_only() || matches!(os, Os::None) {
Abi::SoftFloat
} else if matches!(env, Env::Gnu | Env::Musl | Env::Android) {
Abi::DoubleFloat
} else {
Abi::SoftFloat
}
}
Arch::Riscv64 | Arch::Riscv32 | Arch::LoongArch64 => match os {
Os::None => Abi::SoftFloat,
_ => Abi::DoubleFloat,
},
_ => Abi::DoubleFloat,
}
}
pub const fn is_valid_for(self, arch: Arch) -> bool {
match self {
Abi::Default => true,
Abi::SoftFp => matches!(arch, Arch::Arm),
Abi::SingleFloat => matches!(arch, Arch::Riscv64 | Arch::Riscv32),
Abi::SoftFloat | Abi::DoubleFloat => arch.selects_float_abi(),
}
}
pub fn to_mabi(self, arch: Arch, model: DataModel) -> Option<String> {
let resolved = self;
match arch {
Arch::Riscv64 | Arch::Riscv32 | Arch::LoongArch64 => {
let base = match model {
DataModel::Lp64 => "lp64",
DataModel::Ilp32 | DataModel::Ilp32On64 => "ilp32",
DataModel::Llp64 => return None,
};
let suffix = match resolved {
Abi::SoftFloat => "",
Abi::SingleFloat => "f",
Abi::DoubleFloat => "d",
Abi::Default | Abi::SoftFp => return None,
};
Some(format!("{base}{suffix}"))
}
_ => None,
}
}
}
impl fmt::Display for Abi {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ObjectFormat {
Elf,
MachO,
Coff,
Wasm,
}
impl ObjectFormat {
pub const fn as_str(self) -> &'static str {
match self {
ObjectFormat::Elf => "elf",
ObjectFormat::MachO => "macho",
ObjectFormat::Coff => "coff",
ObjectFormat::Wasm => "wasm",
}
}
pub const fn object_extension(self) -> &'static str {
match self {
ObjectFormat::Coff => "obj",
_ => "o",
}
}
pub const fn archive_extension(self) -> &'static str {
match self {
ObjectFormat::Coff => "lib",
_ => "a",
}
}
pub const fn leading_underscore(self, data_model: DataModel) -> bool {
match self {
ObjectFormat::MachO => true,
ObjectFormat::Coff => matches!(data_model, DataModel::Ilp32),
ObjectFormat::Elf | ObjectFormat::Wasm => false,
}
}
}
impl fmt::Display for ObjectFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}