1
Fork 0

Never create an temporary PassMode::Direct when it is not a valid pass mode for a type

This commit is contained in:
bjorn3 2020-12-29 20:00:57 +01:00
parent ba484de538
commit a93dace55c
2 changed files with 46 additions and 50 deletions

View file

@ -434,31 +434,49 @@ pub struct ArgAbi<'a, Ty> {
}
impl<'a, Ty> ArgAbi<'a, Ty> {
pub fn new(layout: TyAndLayout<'a, Ty>) -> Self {
ArgAbi { layout, pad: None, mode: PassMode::Direct(ArgAttributes::new()) }
pub fn 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) {
match self.mode {
PassMode::Direct(_) | PassMode::Pair(_, _) => {}
_ => panic!("Tried to make {:?} indirect", self.mode),
}
// Start with fresh attributes for the pointer.
fn indirect_pass_mode(layout: &TyAndLayout<'a, Ty>) -> PassMode {
let mut attrs = ArgAttributes::new();
// For non-immediate arguments the callee gets its own copy of
// the value on the stack, so there are no aliases. It's also
// program-invisible so can't possibly capture
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
// 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) {
@ -489,10 +507,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
}
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());
}