Never create an temporary PassMode::Direct when it is not a valid pass mode for a type
This commit is contained in:
parent
ba484de538
commit
a93dace55c
2 changed files with 46 additions and 50 deletions
|
@ -2745,7 +2745,11 @@ where
|
||||||
cx.layout_of(ty)
|
cx.layout_of(ty)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut arg = ArgAbi::new(layout);
|
let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| {
|
||||||
|
let mut attrs = ArgAttributes::new();
|
||||||
|
adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return);
|
||||||
|
attrs
|
||||||
|
});
|
||||||
|
|
||||||
if arg.layout.is_zst() {
|
if arg.layout.is_zst() {
|
||||||
// For some forsaken reason, x86_64-pc-windows-gnu
|
// For some forsaken reason, x86_64-pc-windows-gnu
|
||||||
|
@ -2762,27 +2766,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Abi::ScalarPair(ref a, ref b) = arg.layout.abi {
|
|
||||||
let mut a_attrs = ArgAttributes::new();
|
|
||||||
let mut b_attrs = ArgAttributes::new();
|
|
||||||
adjust_for_rust_scalar(&mut a_attrs, a, arg.layout, Size::ZERO, is_return);
|
|
||||||
adjust_for_rust_scalar(
|
|
||||||
&mut b_attrs,
|
|
||||||
b,
|
|
||||||
arg.layout,
|
|
||||||
a.value.size(cx).align_to(b.value.align(cx).abi),
|
|
||||||
is_return,
|
|
||||||
);
|
|
||||||
arg.mode = PassMode::Pair(a_attrs, b_attrs);
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Abi::Scalar(ref scalar) = arg.layout.abi {
|
|
||||||
if let PassMode::Direct(ref mut attrs) = arg.mode {
|
|
||||||
adjust_for_rust_scalar(attrs, scalar, arg.layout, Size::ZERO, is_return);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
arg
|
arg
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2859,9 +2842,12 @@ where
|
||||||
let max_by_val_size = Pointer.size(cx) * 2;
|
let max_by_val_size = Pointer.size(cx) * 2;
|
||||||
let size = arg.layout.size;
|
let size = arg.layout.size;
|
||||||
|
|
||||||
if arg.layout.is_unsized() || size > max_by_val_size {
|
assert!(
|
||||||
arg.make_indirect();
|
matches!(arg.mode, PassMode::Indirect { on_stack: false, .. }),
|
||||||
} else {
|
"{:?}",
|
||||||
|
arg
|
||||||
|
);
|
||||||
|
if !arg.layout.is_unsized() && size <= max_by_val_size {
|
||||||
// We want to pass small aggregates as immediates, but using
|
// We want to pass small aggregates as immediates, but using
|
||||||
// a LLVM aggregate type for this leads to bad optimizations,
|
// a LLVM aggregate type for this leads to bad optimizations,
|
||||||
// so we pick an appropriately sized integer type instead.
|
// so we pick an appropriately sized integer type instead.
|
||||||
|
@ -2881,15 +2867,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_thin_self_ptr<'tcx, C>(
|
fn make_thin_self_ptr<'tcx, C>(cx: &C, mut layout: TyAndLayout<'tcx>) -> TyAndLayout<'tcx>
|
||||||
cx: &C,
|
where
|
||||||
mut layout: TyAndLayout<'tcx>,
|
C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
|
||||||
) -> TyAndLayout<'tcx>
|
|
||||||
where C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
|
|
||||||
//+ HasDataLayout
|
|
||||||
//+ HasTargetSpec
|
|
||||||
+ HasTyCtxt<'tcx>
|
+ HasTyCtxt<'tcx>
|
||||||
+ HasParamEnv<'tcx>
|
+ HasParamEnv<'tcx>,
|
||||||
{
|
{
|
||||||
let fat_pointer_ty = if layout.is_unsized() {
|
let fat_pointer_ty = if layout.is_unsized() {
|
||||||
// unsized `self` is passed as a pointer to `self`
|
// unsized `self` is passed as a pointer to `self`
|
||||||
|
|
|
@ -434,31 +434,49 @@ pub struct ArgAbi<'a, Ty> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Ty> ArgAbi<'a, Ty> {
|
impl<'a, Ty> ArgAbi<'a, Ty> {
|
||||||
pub fn new(layout: TyAndLayout<'a, Ty>) -> Self {
|
pub fn new(
|
||||||
ArgAbi { layout, pad: None, mode: PassMode::Direct(ArgAttributes::new()) }
|
cx: &impl HasDataLayout,
|
||||||
|
layout: TyAndLayout<'a, Ty>,
|
||||||
|
scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, &abi::Scalar, Size) -> ArgAttributes,
|
||||||
|
) -> Self {
|
||||||
|
let mode = match &layout.abi {
|
||||||
|
Abi::Uninhabited => PassMode::Ignore,
|
||||||
|
Abi::Scalar(scalar) => PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)),
|
||||||
|
Abi::ScalarPair(a, b) => PassMode::Pair(
|
||||||
|
scalar_attrs(&layout, a, Size::ZERO),
|
||||||
|
scalar_attrs(&layout, b, a.value.size(cx).align_to(b.value.align(cx).abi)),
|
||||||
|
),
|
||||||
|
Abi::Vector { .. } => PassMode::Direct(ArgAttributes::new()),
|
||||||
|
Abi::Aggregate { .. } => Self::indirect_pass_mode(&layout),
|
||||||
|
};
|
||||||
|
ArgAbi { layout, pad: None, mode }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_indirect(&mut self) {
|
fn indirect_pass_mode(layout: &TyAndLayout<'a, Ty>) -> PassMode {
|
||||||
match self.mode {
|
|
||||||
PassMode::Direct(_) | PassMode::Pair(_, _) => {}
|
|
||||||
_ => panic!("Tried to make {:?} indirect", self.mode),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start with fresh attributes for the pointer.
|
|
||||||
let mut attrs = ArgAttributes::new();
|
let mut attrs = ArgAttributes::new();
|
||||||
|
|
||||||
// For non-immediate arguments the callee gets its own copy of
|
// For non-immediate arguments the callee gets its own copy of
|
||||||
// the value on the stack, so there are no aliases. It's also
|
// the value on the stack, so there are no aliases. It's also
|
||||||
// program-invisible so can't possibly capture
|
// program-invisible so can't possibly capture
|
||||||
attrs.set(ArgAttribute::NoAlias).set(ArgAttribute::NoCapture).set(ArgAttribute::NonNull);
|
attrs.set(ArgAttribute::NoAlias).set(ArgAttribute::NoCapture).set(ArgAttribute::NonNull);
|
||||||
attrs.pointee_size = self.layout.size;
|
attrs.pointee_size = layout.size;
|
||||||
// FIXME(eddyb) We should be doing this, but at least on
|
// FIXME(eddyb) We should be doing this, but at least on
|
||||||
// i686-pc-windows-msvc, it results in wrong stack offsets.
|
// i686-pc-windows-msvc, it results in wrong stack offsets.
|
||||||
// attrs.pointee_align = Some(self.layout.align.abi);
|
// attrs.pointee_align = Some(layout.align.abi);
|
||||||
|
|
||||||
let extra_attrs = self.layout.is_unsized().then_some(ArgAttributes::new());
|
let extra_attrs = layout.is_unsized().then_some(ArgAttributes::new());
|
||||||
|
|
||||||
self.mode = PassMode::Indirect { attrs, extra_attrs, on_stack: false };
|
PassMode::Indirect { attrs, extra_attrs, on_stack: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_indirect(&mut self) {
|
||||||
|
match self.mode {
|
||||||
|
PassMode::Direct(_) | PassMode::Pair(_, _) => {}
|
||||||
|
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: false } => return,
|
||||||
|
_ => panic!("Tried to make {:?} indirect", self.mode),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mode = Self::indirect_pass_mode(&self.layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_indirect_byval(&mut self) {
|
pub fn make_indirect_byval(&mut self) {
|
||||||
|
@ -489,10 +507,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cast_to<T: Into<CastTarget>>(&mut self, target: T) {
|
pub fn cast_to<T: Into<CastTarget>>(&mut self, target: T) {
|
||||||
match self.mode {
|
|
||||||
PassMode::Direct(_) | PassMode::Pair(_, _) => {}
|
|
||||||
_ => panic!("Tried to cast {:?} to {:?}", self.mode, target.into()),
|
|
||||||
}
|
|
||||||
self.mode = PassMode::Cast(target.into());
|
self.mode = PassMode::Cast(target.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue