about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2020-03-10 20:41:31 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2020-03-10 20:41:31 +0100
commit240d56c33c1a0b7097e7b7da475f61fa1d57400f (patch)
tree46f1844ac5aad923f8ec3b7d19ccce384d3ac8f2
parentc53297f5ebe46f4d3ef0627c985a03871bd23780 (diff)
Support virtual calls with unsized self argument
-rw-r--r--src/abi/mod.rs6
-rw-r--r--src/common.rs4
-rw-r--r--src/pointer.rs7
-rw-r--r--src/value_and_place.rs21
-rw-r--r--src/vtable.rs11
5 files changed, 23 insertions, 26 deletions
diff --git a/src/abi/mod.rs b/src/abi/mod.rs
index 568165bc61d..230cba3a934 100644
--- a/src/abi/mod.rs
+++ b/src/abi/mod.rs
@@ -355,7 +355,7 @@ pub fn codegen_fn_prelude(fx: &mut FunctionCx<'_, '_, impl Backend>, start_block
         // not mutated by the current function, this is necessary to support unsized arguments.
         match arg_kind {
             ArgKind::Normal(Some(val)) => {
-                if let Some((addr, meta)) = val.try_to_addr() {
+                if let Some((addr, meta)) = val.try_to_ptr() {
                     let local_decl = &fx.mir.local_decls[local];
                     //                       v this ! is important
                     let internally_mutable = !val.layout().ty.is_freeze(
@@ -368,9 +368,9 @@ pub fn codegen_fn_prelude(fx: &mut FunctionCx<'_, '_, impl Backend>, start_block
                         // of this argument, to prevent a copy.
 
                         let place = if let Some(meta) = meta {
-                            CPlace::for_ptr_with_extra(Pointer::new(addr), meta, val.layout())
+                            CPlace::for_ptr_with_extra(addr, meta, val.layout())
                         } else {
-                            CPlace::for_ptr(Pointer::new(addr), val.layout())
+                            CPlace::for_ptr(addr, val.layout())
                         };
 
                         #[cfg(debug_assertions)]
diff --git a/src/common.rs b/src/common.rs
index d9659f42d6f..5d99b385779 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -353,7 +353,9 @@ impl<'tcx, B: Backend + 'static> FunctionCx<'_, 'tcx, B> {
     }
 
     pub fn get_local_place(&mut self, local: Local) -> CPlace<'tcx> {
-        *self.local_map.get(&local).unwrap()
+        *self.local_map.get(&local).unwrap_or_else(|| {
+            panic!("Local {:?} doesn't exist", local);
+        })
     }
 
     pub fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {
diff --git a/src/pointer.rs b/src/pointer.rs
index 8ba9582f554..0ecb0e1274e 100644
--- a/src/pointer.rs
+++ b/src/pointer.rs
@@ -55,13 +55,6 @@ impl Pointer {
         }
     }
 
-    pub fn try_get_addr_and_offset(self) -> Option<(Value, Offset32)> {
-        match self.base {
-            PointerBase::Addr(addr) => Some((addr, self.offset)),
-            PointerBase::Stack(_) => None,
-        }
-    }
-
     pub fn offset<'a, 'tcx>(
         self,
         fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
diff --git a/src/value_and_place.rs b/src/value_and_place.rs
index c075fe45544..9024d59ecb4 100644
--- a/src/value_and_place.rs
+++ b/src/value_and_place.rs
@@ -105,19 +105,9 @@ impl<'tcx> CValue<'tcx> {
         }
     }
 
-    pub fn try_to_addr(self) -> Option<(Value, Option<Value>)> {
+    pub fn try_to_ptr(self) -> Option<(Pointer, Option<Value>)> {
         match self.0 {
-            CValueInner::ByRef(ptr, meta) => {
-                if let Some((base_addr, offset)) = ptr.try_get_addr_and_offset() {
-                    if offset == Offset32::new(0) {
-                        Some((base_addr, meta))
-                    } else {
-                        None
-                    }
-                } else {
-                    None
-                }
-            }
+            CValueInner::ByRef(ptr, meta) => Some((ptr, meta)),
             CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => None,
         }
     }
@@ -345,8 +335,11 @@ impl<'tcx> CPlace<'tcx> {
                 CValue::by_val(val, layout)
             }
             CPlaceInner::Addr(ptr, extra) => {
-                assert!(extra.is_none(), "unsized values are not yet supported");
-                CValue::by_ref(ptr, layout)
+                if let Some(extra) = extra {
+                    CValue::by_ref_unsized(ptr, extra, layout)
+                } else {
+                    CValue::by_ref(ptr, layout)
+                }
             }
             CPlaceInner::NoPlace => CValue::by_ref(
                 Pointer::const_addr(fx, i64::try_from(self.layout.align.pref.bytes()).unwrap()),
diff --git a/src/vtable.rs b/src/vtable.rs
index 5ce975d3124..e4b3a9942cf 100644
--- a/src/vtable.rs
+++ b/src/vtable.rs
@@ -47,7 +47,16 @@ pub fn get_ptr_and_method_ref<'tcx>(
     arg: CValue<'tcx>,
     idx: usize,
 ) -> (Value, Value) {
-    let (ptr, vtable) = arg.load_scalar_pair(fx);
+    let (ptr, vtable) = if let Abi::ScalarPair(_, _) = arg.layout().abi {
+        arg.load_scalar_pair(fx)
+    } else {
+        let (ptr, vtable) = arg.try_to_ptr().unwrap();
+        (
+            ptr.get_addr(fx),
+            vtable.unwrap()
+        )
+    };
+
     let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
     let func_ref = fx.bcx.ins().load(
         pointer_ty(fx.tcx),