1use std::iter;
2
3use rustc_abi::{BackendRepr, HasDataLayout, Primitive, TyAbiInterface};
4
5use crate::callconv::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
6use crate::spec::{Arch, HasTargetSpec, RustcAbi, Target};
7
8#[derive(#[automatically_derived]impl ::core::marker::Copy for AbiKind { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for AbiKind {
}
#[automatically_derived]impl ::core::clone::Clone for AbiKind {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::fmt::Debug for AbiKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
AbiKind::AAPCS => "AAPCS",
AbiKind::DarwinPCS => "DarwinPCS",
AbiKind::Win64 => "Win64",
})
}
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for AbiKind {
}
#[automatically_derived]impl ::core::cmp::PartialEq for AbiKind {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq)]
13pub(crate) enum AbiKind {
14 AAPCS,
15 DarwinPCS,
16 Win64,
17}
18
19{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("is_homogeneous_aggregate",
"rustc_target::callconv::aarch64", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/76456a688bc0ed897fa23a677d4ddb5b3fdb575a/compiler/rustc_target/src/callconv/aarch64.rs"),
::tracing_core::__macro_support::Option::Some(19u32),
::tracing_core::__macro_support::Option::Some("rustc_target::callconv::aarch64"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("arg")
}> =
::tracing::__macro_support::FieldName::new("arg");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&arg)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<Uniform> = loop {};
return __tracing_attr_fake_return;
}
{
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha|
ha.unit()).and_then(|unit|
{
let size = arg.layout.size;
if size > unit.size.checked_mul(4, cx).unwrap() {
return None;
}
let valid_unit =
match unit.kind {
RegKind::Integer => false,
RegKind::PpcF128 =>
::core::panicking::unreachable_default_msg(),
RegKind::Float =>
cx.target_spec().rustc_abi != Some(RustcAbi::Softfloat),
RegKind::Vector { .. } =>
unit.size.bits() == 64 || unit.size.bits() == 128,
};
valid_unit.then_some(Uniform::consecutive(unit, size))
})
}
}
}#[tracing::instrument(skip(cx), level = "debug")]
20fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
21where
22 Ty: TyAbiInterface<'a, C> + Copy,
23 C: HasDataLayout + HasTargetSpec,
24{
25 arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
26 let size = arg.layout.size;
27
28 if size > unit.size.checked_mul(4, cx).unwrap() {
30 return None;
31 }
32
33 let valid_unit = match unit.kind {
34 RegKind::Integer => false,
35 RegKind::PpcF128 => unreachable!(),
36 RegKind::Float => cx.target_spec().rustc_abi != Some(RustcAbi::Softfloat),
39 RegKind::Vector { .. } => unit.size.bits() == 64 || unit.size.bits() == 128,
40 };
41
42 valid_unit.then_some(Uniform::consecutive(unit, size))
43 })
44}
45
46fn softfloat_float_abi<Ty>(target: &Target, arg: &mut ArgAbi<'_, Ty>) {
47 if target.rustc_abi != Some(RustcAbi::Softfloat) {
48 return;
49 }
50 if let BackendRepr::Scalar(s) = arg.layout.backend_repr
57 && let Primitive::Float(f) = s.primitive()
58 {
59 arg.cast_to(Reg { kind: RegKind::Integer, size: f.size() });
60 } else if let BackendRepr::ScalarPair { a: s1, b: s2, b_offset: _ } = arg.layout.backend_repr
61 && (#[allow(non_exhaustive_omitted_patterns)] match s1.primitive() {
Primitive::Float(_) => true,
_ => false,
}matches!(s1.primitive(), Primitive::Float(_))
62 || #[allow(non_exhaustive_omitted_patterns)] match s2.primitive() {
Primitive::Float(_) => true,
_ => false,
}matches!(s2.primitive(), Primitive::Float(_)))
63 {
64 if arg.layout.size.bits() <= target.pointer_width.into() {
71 arg.cast_to(Reg { kind: RegKind::Integer, size: arg.layout.size });
72 } else {
73 arg.make_indirect();
74 }
75 }
76}
77
78{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("classify_ret",
"rustc_target::callconv::aarch64", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/76456a688bc0ed897fa23a677d4ddb5b3fdb575a/compiler/rustc_target/src/callconv/aarch64.rs"),
::tracing_core::__macro_support::Option::Some(78u32),
::tracing_core::__macro_support::Option::Some("rustc_target::callconv::aarch64"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ret")
}> =
::tracing::__macro_support::FieldName::new("ret");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("kind")
}> =
::tracing::__macro_support::FieldName::new("kind");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ret)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&kind)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if !ret.layout.is_sized() || ret.layout.is_scalable_vector() {
return;
}
if !ret.layout.is_aggregate() {
if kind == AbiKind::DarwinPCS {
ret.extend_integer_width_to(32)
}
softfloat_float_abi(cx.target_spec(), ret);
return;
}
if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
ret.cast_to(uniform);
return;
}
let size = ret.layout.size;
let bits = size.bits();
if bits <= 128 {
ret.cast_to(Uniform::new(Reg::i64(), size));
return;
}
ret.make_indirect();
}
}
}#[tracing::instrument(skip(cx), level = "debug")]
79fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, kind: AbiKind)
80where
81 Ty: TyAbiInterface<'a, C> + Copy,
82 C: HasDataLayout + HasTargetSpec,
83{
84 if !ret.layout.is_sized() || ret.layout.is_scalable_vector() {
85 return;
87 }
88 if !ret.layout.is_aggregate() {
89 if kind == AbiKind::DarwinPCS {
90 ret.extend_integer_width_to(32)
94 }
95 softfloat_float_abi(cx.target_spec(), ret);
96 return;
97 }
98 if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
99 ret.cast_to(uniform);
100 return;
101 }
102 let size = ret.layout.size;
103 let bits = size.bits();
104 if bits <= 128 {
105 ret.cast_to(Uniform::new(Reg::i64(), size));
106 return;
107 }
108 ret.make_indirect();
109}
110
111{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("classify_arg",
"rustc_target::callconv::aarch64", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/76456a688bc0ed897fa23a677d4ddb5b3fdb575a/compiler/rustc_target/src/callconv/aarch64.rs"),
::tracing_core::__macro_support::Option::Some(111u32),
::tracing_core::__macro_support::Option::Some("rustc_target::callconv::aarch64"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("arg")
}> =
::tracing::__macro_support::FieldName::new("arg");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("kind")
}> =
::tracing::__macro_support::FieldName::new("kind");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&arg)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&kind)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if !arg.layout.is_sized() || arg.layout.is_scalable_vector() {
return;
}
if arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
arg.make_indirect();
return;
}
if !arg.layout.is_aggregate() {
if kind == AbiKind::DarwinPCS {
arg.extend_integer_width_to(32);
}
softfloat_float_abi(cx.target_spec(), arg);
return;
}
if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
arg.cast_to(uniform);
return;
}
let size = arg.layout.size;
let align =
if kind == AbiKind::AAPCS {
arg.layout.unadjusted_abi_align
} else { arg.layout.align.abi };
if size.bits() <= 128 {
if align.bits() == 128 {
arg.cast_to(Uniform::new(Reg::i128(), size));
} else { arg.cast_to(Uniform::new(Reg::i64(), size)); }
return;
}
arg.make_indirect();
}
}
}#[tracing::instrument(skip(cx), level = "debug")]
112fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, kind: AbiKind)
113where
114 Ty: TyAbiInterface<'a, C> + Copy,
115 C: HasDataLayout + HasTargetSpec,
116{
117 if !arg.layout.is_sized() || arg.layout.is_scalable_vector() {
118 return;
120 }
121 if arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
122 arg.make_indirect();
123 return;
124 }
125 if !arg.layout.is_aggregate() {
126 if kind == AbiKind::DarwinPCS {
127 arg.extend_integer_width_to(32);
131 }
132 softfloat_float_abi(cx.target_spec(), arg);
133
134 return;
135 }
136 if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
137 arg.cast_to(uniform);
138 return;
139 }
140 let size = arg.layout.size;
141 let align = if kind == AbiKind::AAPCS {
142 arg.layout.unadjusted_abi_align
147 } else {
148 arg.layout.align.abi
149 };
150 if size.bits() <= 128 {
151 if align.bits() == 128 {
152 arg.cast_to(Uniform::new(Reg::i128(), size));
153 } else {
154 arg.cast_to(Uniform::new(Reg::i64(), size));
155 }
156 return;
157 }
158 arg.make_indirect();
159}
160
161pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, kind: AbiKind)
162where
163 Ty: TyAbiInterface<'a, C> + Copy,
164 C: HasDataLayout + HasTargetSpec,
165{
166 if !fn_abi.ret.is_ignore() {
167 classify_ret(cx, &mut fn_abi.ret, kind);
168 }
169
170 let c_variadic = fn_abi.c_variadic;
174 let fixed_count = fn_abi.fixed_count as usize;
175 let is_arm64ec = cx.target_spec().arch == Arch::Arm64EC;
176
177 for (idx, arg) in fn_abi.args.iter_mut().enumerate() {
178 if arg.is_ignore() {
179 continue;
180 }
181
182 if is_arm64ec && c_variadic && idx >= fixed_count {
183 let size = arg.layout.size.bytes();
184 if size > 8 || !size.is_power_of_two() {
185 arg.make_indirect();
186 continue;
187 }
188 }
189
190 classify_arg(cx, arg, kind);
191 }
192}
193
194pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
195where
196 Ty: TyAbiInterface<'a, C> + Copy,
197 C: HasDataLayout + HasTargetSpec,
198{
199 for arg in fn_abi.args.iter_mut().chain(iter::once(&mut fn_abi.ret)) {
200 softfloat_float_abi(cx.target_spec(), arg);
201 }
202}