mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +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.
|
// not mutated by the current function, this is necessary to support unsized arguments.
|
||||||
match arg_kind {
|
match arg_kind {
|
||||||
ArgKind::Normal(Some(val)) => {
|
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];
|
let local_decl = &fx.mir.local_decls[local];
|
||||||
// v this ! is important
|
// v this ! is important
|
||||||
let internally_mutable = !val.layout().ty.is_freeze(
|
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.
|
// of this argument, to prevent a copy.
|
||||||
|
|
||||||
let place = if let Some(meta) = meta {
|
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 {
|
} else {
|
||||||
CPlace::for_ptr(Pointer::new(addr), val.layout())
|
CPlace::for_ptr(addr, val.layout())
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[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> {
|
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) {
|
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>(
|
pub fn offset<'a, 'tcx>(
|
||||||
self,
|
self,
|
||||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
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 {
|
match self.0 {
|
||||||
CValueInner::ByRef(ptr, meta) => {
|
CValueInner::ByRef(ptr, meta) => Some((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::ByVal(_) | CValueInner::ByValPair(_, _) => None,
|
CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -345,8 +335,11 @@ impl<'tcx> CPlace<'tcx> {
|
|||||||
CValue::by_val(val, layout)
|
CValue::by_val(val, layout)
|
||||||
}
|
}
|
||||||
CPlaceInner::Addr(ptr, extra) => {
|
CPlaceInner::Addr(ptr, extra) => {
|
||||||
assert!(extra.is_none(), "unsized values are not yet supported");
|
if let Some(extra) = extra {
|
||||||
CValue::by_ref(ptr, layout)
|
CValue::by_ref_unsized(ptr, extra, layout)
|
||||||
|
} else {
|
||||||
|
CValue::by_ref(ptr, layout)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CPlaceInner::NoPlace => CValue::by_ref(
|
CPlaceInner::NoPlace => CValue::by_ref(
|
||||||
Pointer::const_addr(fx, i64::try_from(self.layout.align.pref.bytes()).unwrap()),
|
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>,
|
arg: CValue<'tcx>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
) -> (Value, Value) {
|
) -> (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 usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
|
||||||
let func_ref = fx.bcx.ins().load(
|
let func_ref = fx.bcx.ins().load(
|
||||||
pointer_ty(fx.tcx),
|
pointer_ty(fx.tcx),
|
||||||
|
Loading…
Reference in New Issue
Block a user