about summary refs log tree commit diff
path: root/compiler/rustc_target
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2020-12-29 20:00:57 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2021-01-23 10:30:39 +0100
commita93dace55c588badca5475de570e45063deaf0be (patch)
treeb727c704f7aaa73a29970a8723a83d1e8191473f /compiler/rustc_target
parentba484de538640305b0ba5f574d809c1a71feda26 (diff)
downloadrust-a93dace55c588badca5475de570e45063deaf0be.tar.gz
rust-a93dace55c588badca5475de570e45063deaf0be.zip
Never create an temporary PassMode::Direct when it is not a valid pass mode for a type
Diffstat (limited to 'compiler/rustc_target')
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs48
1 files changed, 31 insertions, 17 deletions
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 24fd11b6772..e889c3c415c 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -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());
     }