]> git.lizzy.rs Git - rust.git/commitdiff
Fix virtual function calls
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 23 Mar 2017 13:57:11 +0000 (14:57 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 23 Mar 2017 13:57:11 +0000 (14:57 +0100)
src/terminator/mod.rs

index a6e0e53c2ded976fd8d2965c677fa021064773d3..fa74e57132035708233141cae727a03a29a57615 100644 (file)
@@ -287,57 +287,18 @@ fn eval_fn_call(
                 Ok(())
             },
             ty::InstanceDef::Virtual(_, idx) => {
-                trace!("ABI: {:?}", sig.abi);
-                let mut args = Vec::new();
-                for arg in arg_operands {
-                    let arg_val = self.eval_operand(arg)?;
-                    let arg_ty = self.operand_ty(arg);
-                    args.push((arg_val, arg_ty));
-                }
                 let ptr_size = self.memory.pointer_size();
-                let (_, vtable) = args[0].0.expect_ptr_vtable_pair(&self.memory)?;
-                // FIXME: do we need to rewrite args[0] to be a thin ptr?
+                let (_, vtable) = self.eval_operand(&arg_operands[0])?.expect_ptr_vtable_pair(&self.memory)?;
                 let fn_ptr = self.memory.read_ptr(vtable.offset(ptr_size * (idx as u64 + 3)))?;
                 let instance = self.memory.get_fn(fn_ptr.alloc_id)?;
-                self.eval_fn_call_inner(
+                // recurse with concrete function
+                self.eval_fn_call(
                     instance,
                     destination,
+                    arg_operands,
                     span,
-                )?;
-                match sig.abi {
-                    Abi::RustCall => {
-                        trace!("arg_locals: {:?}", self.frame().mir.args_iter().collect::<Vec<_>>());
-                        trace!("arg_operands: {:?}", arg_operands);
-                        trace!("args: {:#?}", args);
-
-                        assert_eq!(args.len(), 2);
-
-                        {   // write first argument
-                            let first_local = self.frame().mir.args_iter().next().unwrap();
-                            let dest = self.eval_lvalue(&mir::Lvalue::Local(first_local))?;
-                            let (arg_val, arg_ty) = args.remove(0);
-                            self.write_value(arg_val, dest, arg_ty)?;
-                        }
-
-                        // unpack and write all other args
-                        let (arg_val, arg_ty) = args.remove(0);
-                        let layout = self.type_layout(arg_ty)?;
-                        if let (&ty::TyTuple(fields, _), &Layout::Univariant { ref variant, .. }) = (&arg_ty.sty, layout) {
-                            let offsets = variant.offsets.iter().map(|s| s.bytes());
-                            if let Value::ByRef(ptr) = arg_val {
-                                for ((offset, ty), arg_local) in offsets.zip(fields).zip(self.frame().mir.args_iter().skip(1)) {
-                                    let arg = Value::ByRef(ptr.offset(offset));
-                                    let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
-                                    self.write_value(arg, dest, ty)?;
-                                }
-                            }
-                        } else {
-                            bug!("rust-call ABI tuple argument was {:?}, {:?}", arg_ty, layout);
-                        }
-                    },
-                    _ => unimplemented!(),
-                }
-                Ok(())
+                    sig,
+                )
             },
         }
     }