Skip to content

Commit a93dace

Browse files
committed
Never create an temporary PassMode::Direct when it is not a valid pass mode for a type
1 parent ba484de commit a93dace

File tree

2 files changed

+46
-50
lines changed

2 files changed

+46
-50
lines changed

Diff for: compiler/rustc_middle/src/ty/layout.rs

+15-33
Original file line numberDiff line numberDiff line change
@@ -2745,7 +2745,11 @@ where
27452745
cx.layout_of(ty)
27462746
};
27472747

2748-
let mut arg = ArgAbi::new(layout);
2748+
let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| {
2749+
let mut attrs = ArgAttributes::new();
2750+
adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return);
2751+
attrs
2752+
});
27492753

27502754
if arg.layout.is_zst() {
27512755
// For some forsaken reason, x86_64-pc-windows-gnu
@@ -2762,27 +2766,6 @@ where
27622766
}
27632767
}
27642768

2765-
if let Abi::ScalarPair(ref a, ref b) = arg.layout.abi {
2766-
let mut a_attrs = ArgAttributes::new();
2767-
let mut b_attrs = ArgAttributes::new();
2768-
adjust_for_rust_scalar(&mut a_attrs, a, arg.layout, Size::ZERO, is_return);
2769-
adjust_for_rust_scalar(
2770-
&mut b_attrs,
2771-
b,
2772-
arg.layout,
2773-
a.value.size(cx).align_to(b.value.align(cx).abi),
2774-
is_return,
2775-
);
2776-
arg.mode = PassMode::Pair(a_attrs, b_attrs);
2777-
return arg;
2778-
}
2779-
2780-
if let Abi::Scalar(ref scalar) = arg.layout.abi {
2781-
if let PassMode::Direct(ref mut attrs) = arg.mode {
2782-
adjust_for_rust_scalar(attrs, scalar, arg.layout, Size::ZERO, is_return);
2783-
}
2784-
}
2785-
27862769
arg
27872770
};
27882771

@@ -2859,9 +2842,12 @@ where
28592842
let max_by_val_size = Pointer.size(cx) * 2;
28602843
let size = arg.layout.size;
28612844

2862-
if arg.layout.is_unsized() || size > max_by_val_size {
2863-
arg.make_indirect();
2864-
} else {
2845+
assert!(
2846+
matches!(arg.mode, PassMode::Indirect { on_stack: false, .. }),
2847+
"{:?}",
2848+
arg
2849+
);
2850+
if !arg.layout.is_unsized() && size <= max_by_val_size {
28652851
// We want to pass small aggregates as immediates, but using
28662852
// a LLVM aggregate type for this leads to bad optimizations,
28672853
// so we pick an appropriately sized integer type instead.
@@ -2881,15 +2867,11 @@ where
28812867
}
28822868
}
28832869

2884-
fn make_thin_self_ptr<'tcx, C>(
2885-
cx: &C,
2886-
mut layout: TyAndLayout<'tcx>,
2887-
) -> TyAndLayout<'tcx>
2888-
where C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
2889-
//+ HasDataLayout
2890-
//+ HasTargetSpec
2870+
fn make_thin_self_ptr<'tcx, C>(cx: &C, mut layout: TyAndLayout<'tcx>) -> TyAndLayout<'tcx>
2871+
where
2872+
C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
28912873
+ HasTyCtxt<'tcx>
2892-
+ HasParamEnv<'tcx>
2874+
+ HasParamEnv<'tcx>,
28932875
{
28942876
let fat_pointer_ty = if layout.is_unsized() {
28952877
// unsized `self` is passed as a pointer to `self`

Diff for: compiler/rustc_target/src/abi/call/mod.rs

+31-17
Original file line numberDiff line numberDiff line change
@@ -434,31 +434,49 @@ pub struct ArgAbi<'a, Ty> {
434434
}
435435

436436
impl<'a, Ty> ArgAbi<'a, Ty> {
437-
pub fn new(layout: TyAndLayout<'a, Ty>) -> Self {
438-
ArgAbi { layout, pad: None, mode: PassMode::Direct(ArgAttributes::new()) }
437+
pub fn new(
438+
cx: &impl HasDataLayout,
439+
layout: TyAndLayout<'a, Ty>,
440+
scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, &abi::Scalar, Size) -> ArgAttributes,
441+
) -> Self {
442+
let mode = match &layout.abi {
443+
Abi::Uninhabited => PassMode::Ignore,
444+
Abi::Scalar(scalar) => PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)),
445+
Abi::ScalarPair(a, b) => PassMode::Pair(
446+
scalar_attrs(&layout, a, Size::ZERO),
447+
scalar_attrs(&layout, b, a.value.size(cx).align_to(b.value.align(cx).abi)),
448+
),
449+
Abi::Vector { .. } => PassMode::Direct(ArgAttributes::new()),
450+
Abi::Aggregate { .. } => Self::indirect_pass_mode(&layout),
451+
};
452+
ArgAbi { layout, pad: None, mode }
439453
}
440454

441-
pub fn make_indirect(&mut self) {
442-
match self.mode {
443-
PassMode::Direct(_) | PassMode::Pair(_, _) => {}
444-
_ => panic!("Tried to make {:?} indirect", self.mode),
445-
}
446-
447-
// Start with fresh attributes for the pointer.
455+
fn indirect_pass_mode(layout: &TyAndLayout<'a, Ty>) -> PassMode {
448456
let mut attrs = ArgAttributes::new();
449457

450458
// For non-immediate arguments the callee gets its own copy of
451459
// the value on the stack, so there are no aliases. It's also
452460
// program-invisible so can't possibly capture
453461
attrs.set(ArgAttribute::NoAlias).set(ArgAttribute::NoCapture).set(ArgAttribute::NonNull);
454-
attrs.pointee_size = self.layout.size;
462+
attrs.pointee_size = layout.size;
455463
// FIXME(eddyb) We should be doing this, but at least on
456464
// i686-pc-windows-msvc, it results in wrong stack offsets.
457-
// attrs.pointee_align = Some(self.layout.align.abi);
465+
// attrs.pointee_align = Some(layout.align.abi);
458466

459-
let extra_attrs = self.layout.is_unsized().then_some(ArgAttributes::new());
467+
let extra_attrs = layout.is_unsized().then_some(ArgAttributes::new());
460468

461-
self.mode = PassMode::Indirect { attrs, extra_attrs, on_stack: false };
469+
PassMode::Indirect { attrs, extra_attrs, on_stack: false }
470+
}
471+
472+
pub fn make_indirect(&mut self) {
473+
match self.mode {
474+
PassMode::Direct(_) | PassMode::Pair(_, _) => {}
475+
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: false } => return,
476+
_ => panic!("Tried to make {:?} indirect", self.mode),
477+
}
478+
479+
self.mode = Self::indirect_pass_mode(&self.layout);
462480
}
463481

464482
pub fn make_indirect_byval(&mut self) {
@@ -489,10 +507,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
489507
}
490508

491509
pub fn cast_to<T: Into<CastTarget>>(&mut self, target: T) {
492-
match self.mode {
493-
PassMode::Direct(_) | PassMode::Pair(_, _) => {}
494-
_ => panic!("Tried to cast {:?} to {:?}", self.mode, target.into()),
495-
}
496510
self.mode = PassMode::Cast(target.into());
497511
}
498512

0 commit comments

Comments
 (0)