use rucc_tuple::{Arch, Os, TargetTuple};
use crate::describe::{
AbiDescription, Banks, ReturnPointer, Rule, Scalars, Short, StackArgs, Test, Travel, Variadic,
};
use crate::shape::Format;
pub static SYSV_AMD64: AbiDescription = AbiDescription {
name: "SysV AMD64",
banks: Banks { integer: 6, float: 8, shared: false, integer_width: 8, float_width: 16 },
scalars: Scalars { in_memory: Some(Format::X87Extended), wide_integer_is_all_or_nothing: true },
returns: &[
Rule::new(Test::Empty, Travel::Ignore),
Rule::new(Test::X87Stack, Travel::AsFound),
Rule::new(Test::Eightbytes { limit: 16 }, Travel::AsFound),
Rule::new(Test::Anything, Travel::ByReference),
],
arguments: &[
Rule::new(Test::Empty, Travel::Ignore),
Rule::new(Test::Eightbytes { limit: 16 }, Travel::AsFound).short(Short::Memory),
Rule::new(Test::Anything, Travel::InMemory),
],
return_pointer: ReturnPointer::FirstArgument,
variadic: Variadic::SameAsFixed,
stack_args: StackArgs::RegisterSized,
};
const AAPCS64_BASE: AbiDescription = AbiDescription {
name: "AAPCS64",
banks: Banks { integer: 8, float: 8, shared: false, integer_width: 8, float_width: 16 },
scalars: Scalars { in_memory: None, wide_integer_is_all_or_nothing: false },
returns: &[
Rule::new(Test::Empty, Travel::Ignore),
Rule::new(Test::Homogeneous { limit: 4 }, Travel::AsFound),
Rule::new(Test::SizeAtMost(16), Travel::AsIntegers),
Rule::new(Test::Anything, Travel::ByReference),
],
arguments: &[
Rule::new(Test::Empty, Travel::Ignore),
Rule::new(Test::Homogeneous { limit: 4 }, Travel::AsFound).short(Short::MemoryAndDrain),
Rule::new(Test::SizeAtMost(16), Travel::AsIntegers).short(Short::MemoryAndDrain),
Rule::new(Test::Anything, Travel::ByReference),
],
return_pointer: ReturnPointer::Dedicated,
variadic: Variadic::SameAsFixed,
stack_args: StackArgs::RegisterSized,
};
pub static AAPCS64: AbiDescription = AAPCS64_BASE;
pub static DARWIN_ARM64: AbiDescription = AbiDescription {
name: "Darwin arm64",
variadic: Variadic::AlwaysMemory,
stack_args: StackArgs::Packed,
..AAPCS64_BASE
};
pub static WIN64: AbiDescription = AbiDescription {
name: "Windows x64",
banks: Banks { integer: 4, float: 0, shared: true, integer_width: 8, float_width: 16 },
scalars: Scalars { in_memory: None, wide_integer_is_all_or_nothing: false },
returns: &[
Rule::new(Test::Empty, Travel::Ignore),
Rule::new(Test::SizeOneOf(&[1, 2, 4, 8]), Travel::AsOneInteger),
Rule::new(Test::Anything, Travel::ByReference),
],
arguments: &[
Rule::new(Test::Empty, Travel::Ignore),
Rule::new(Test::SizeOneOf(&[1, 2, 4, 8]), Travel::AsOneInteger),
Rule::new(Test::Anything, Travel::ByReference),
],
return_pointer: ReturnPointer::FirstArgument,
variadic: Variadic::BothBanks,
stack_args: StackArgs::RegisterSized,
};
pub static RISCV_LP64D: AbiDescription = AbiDescription {
name: "RISC-V LP64D",
banks: Banks { integer: 8, float: 8, shared: false, integer_width: 8, float_width: 8 },
scalars: Scalars { in_memory: None, wide_integer_is_all_or_nothing: false },
returns: &[
Rule::new(Test::Empty, Travel::Ignore),
Rule::new(Test::FloatPair, Travel::AsFound),
Rule::new(Test::SizeAtMost(16), Travel::AsIntegers),
Rule::new(Test::Anything, Travel::ByReference),
],
arguments: &[
Rule::new(Test::Empty, Travel::Ignore),
Rule::new(Test::FloatPair, Travel::AsFound).short(Short::TryNextRule),
Rule::new(Test::SizeAtMost(16), Travel::AsIntegers).short(Short::MemoryAndDrain),
Rule::new(Test::Anything, Travel::ByReference),
],
return_pointer: ReturnPointer::FirstArgument,
variadic: Variadic::SameAsFixed,
stack_args: StackArgs::RegisterSized,
};
pub static DESCRIBED: &[&AbiDescription] =
&[&SYSV_AMD64, &AAPCS64, &DARWIN_ARM64, &WIN64, &RISCV_LP64D];
#[must_use]
pub fn for_target(target: TargetTuple) -> Option<&'static AbiDescription> {
Some(match (target.arch(), target.os()) {
(Arch::X86_64, Os::Windows) => &WIN64,
(Arch::X86_64, _) => &SYSV_AMD64,
(Arch::Aarch64, os) if os.is_darwin() => &DARWIN_ARM64,
(Arch::Aarch64, Os::Windows) => return None,
(Arch::Aarch64, _) => &AAPCS64,
(Arch::Riscv64, _) => &RISCV_LP64D,
_ => return None,
})
}