Move some code around

This commit is contained in:
bjorn3 2020-12-28 16:34:05 +01:00
parent da0309c711
commit ba484de538

View File

@ -2514,7 +2514,7 @@ where
extra_args: &[Ty<'tcx>],
caller_location: Option<Ty<'tcx>>,
codegen_fn_attr_flags: CodegenFnAttrFlags,
mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgAbi<'tcx, Ty<'tcx>>,
make_self_ptr_thin: bool,
) -> Self;
fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi);
}
@ -2574,9 +2574,7 @@ where
// Assume that fn pointers may always unwind
let codegen_fn_attr_flags = CodegenFnAttrFlags::UNWIND;
call::FnAbi::new_internal(cx, sig, extra_args, None, codegen_fn_attr_flags, |ty, _| {
ArgAbi::new(cx.layout_of(ty))
})
call::FnAbi::new_internal(cx, sig, extra_args, None, codegen_fn_attr_flags, false)
}
fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
@ -2590,55 +2588,14 @@ where
let attrs = cx.tcx().codegen_fn_attrs(instance.def_id()).flags;
call::FnAbi::new_internal(cx, sig, extra_args, caller_location, attrs, |ty, arg_idx| {
let mut layout = cx.layout_of(ty);
// Don't pass the vtable, it's not an argument of the virtual fn.
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
// or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
if let (ty::InstanceDef::Virtual(..), Some(0)) = (&instance.def, arg_idx) {
let fat_pointer_ty = if layout.is_unsized() {
// unsized `self` is passed as a pointer to `self`
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
cx.tcx().mk_mut_ptr(layout.ty)
} else {
match layout.abi {
Abi::ScalarPair(..) => (),
_ => bug!("receiver type has unsupported layout: {:?}", layout),
}
// In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
// with a Scalar (not ScalarPair) ABI. This is a hack that is understood
// elsewhere in the compiler as a method on a `dyn Trait`.
// To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
// get a built-in pointer type
let mut fat_pointer_layout = layout;
'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr()
&& !fat_pointer_layout.ty.is_region_ptr()
{
for i in 0..fat_pointer_layout.fields.count() {
let field_layout = fat_pointer_layout.field(cx, i);
if !field_layout.is_zst() {
fat_pointer_layout = field_layout;
continue 'descend_newtypes;
}
}
bug!("receiver has no non-zero-sized fields {:?}", fat_pointer_layout);
}
fat_pointer_layout.ty
};
// we now have a type like `*mut RcBox<dyn Trait>`
// change its layout to that of `*mut ()`, a thin pointer, but keep the same type
// this is understood as a special case elsewhere in the compiler
let unit_pointer_ty = cx.tcx().mk_mut_ptr(cx.tcx().mk_unit());
layout = cx.layout_of(unit_pointer_ty);
layout.ty = fat_pointer_ty;
}
ArgAbi::new(layout)
})
call::FnAbi::new_internal(
cx,
sig,
extra_args,
caller_location,
attrs,
matches!(instance.def, ty::InstanceDef::Virtual(..)),
)
}
fn new_internal(
@ -2647,7 +2604,7 @@ where
extra_args: &[Ty<'tcx>],
caller_location: Option<Ty<'tcx>>,
codegen_fn_attr_flags: CodegenFnAttrFlags,
mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgAbi<'tcx, Ty<'tcx>>,
force_thin_self_ptr: bool,
) -> Self {
debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args);
@ -2778,7 +2735,18 @@ where
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| {
let is_return = arg_idx.is_none();
let mut arg = mk_arg_type(ty, arg_idx);
let layout = if force_thin_self_ptr && arg_idx == Some(0) {
// Don't pass the vtable, it's not an argument of the virtual fn.
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
// or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
make_thin_self_ptr(cx, cx.layout_of(ty))
} else {
cx.layout_of(ty)
};
let mut arg = ArgAbi::new(layout);
if arg.layout.is_zst() {
// For some forsaken reason, x86_64-pc-windows-gnu
// doesn't ignore zero-sized struct arguments.
@ -2912,3 +2880,56 @@ where
}
}
}
fn make_thin_self_ptr<'tcx, C>(
cx: &C,
mut layout: TyAndLayout<'tcx>,
) -> TyAndLayout<'tcx>
where C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
//+ HasDataLayout
//+ HasTargetSpec
+ HasTyCtxt<'tcx>
+ HasParamEnv<'tcx>
{
let fat_pointer_ty = if layout.is_unsized() {
// unsized `self` is passed as a pointer to `self`
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
cx.tcx().mk_mut_ptr(layout.ty)
} else {
match layout.abi {
Abi::ScalarPair(..) => (),
_ => bug!("receiver type has unsupported layout: {:?}", layout),
}
// In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
// with a Scalar (not ScalarPair) ABI. This is a hack that is understood
// elsewhere in the compiler as a method on a `dyn Trait`.
// To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
// get a built-in pointer type
let mut fat_pointer_layout = layout;
'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr()
&& !fat_pointer_layout.ty.is_region_ptr()
{
for i in 0..fat_pointer_layout.fields.count() {
let field_layout = fat_pointer_layout.field(cx, i);
if !field_layout.is_zst() {
fat_pointer_layout = field_layout;
continue 'descend_newtypes;
}
}
bug!("receiver has no non-zero-sized fields {:?}", fat_pointer_layout);
}
fat_pointer_layout.ty
};
// we now have a type like `*mut RcBox<dyn Trait>`
// change its layout to that of `*mut ()`, a thin pointer, but keep the same type
// this is understood as a special case elsewhere in the compiler
let unit_pointer_ty = cx.tcx().mk_mut_ptr(cx.tcx().mk_unit());
layout = cx.layout_of(unit_pointer_ty);
layout.ty = fat_pointer_ty;
layout
}