Support virtual calls with unsized self argument

This commit is contained in:
bjorn3 2020-03-10 20:41:31 +01:00
parent c53297f5eb
commit 240d56c33c
5 changed files with 23 additions and 26 deletions

View File

@ -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)]

View File

@ -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) {

View File

@ -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>,

View File

@ -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()),

View File

@ -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),