mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 15:54:15 +00:00
Support virtual calls with unsized self argument
This commit is contained in:
parent
c53297f5eb
commit
240d56c33c
@ -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)]
|
||||
|
@ -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) {
|
||||
|
@ -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>,
|
||||
|
@ -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()),
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user