1
Fork 0

Merge commit '9a0c32934e' into sync_cg_clif-2021-03-05

This commit is contained in:
bjorn3 2021-03-05 19:12:59 +01:00
commit 7a6ea77473
73 changed files with 1145 additions and 2596 deletions

View file

@ -10,14 +10,14 @@ use cranelift_codegen::entity::EntityRef;
use crate::prelude::*;
pub(super) fn add_args_header_comment(fx: &mut FunctionCx<'_, '_, impl Module>) {
pub(super) fn add_args_header_comment(fx: &mut FunctionCx<'_, '_, '_>) {
fx.add_global_comment(
"kind loc.idx param pass mode ty".to_string(),
);
}
pub(super) fn add_arg_comment<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
fx: &mut FunctionCx<'_, '_, 'tcx>,
kind: &str,
local: Option<mir::Local>,
local_field: Option<usize>,
@ -42,11 +42,7 @@ pub(super) fn add_arg_comment<'tcx>(
[param_a, param_b] => Cow::Owned(format!("= {:?},{:?}", param_a, param_b)),
params => Cow::Owned(format!(
"= {}",
params
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(",")
params.iter().map(ToString::to_string).collect::<Vec<_>>().join(",")
)),
};
@ -62,7 +58,7 @@ pub(super) fn add_arg_comment<'tcx>(
));
}
pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, impl Module>) {
pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, '_>) {
fx.add_global_comment(String::new());
fx.add_global_comment(
"kind local ty size align (abi,pref)".to_string(),
@ -70,19 +66,13 @@ pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, impl Module>
}
pub(super) fn add_local_place_comments<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
fx: &mut FunctionCx<'_, '_, 'tcx>,
place: CPlace<'tcx>,
local: Local,
) {
let TyAndLayout { ty, layout } = place.layout();
let rustc_target::abi::Layout {
size,
align,
abi: _,
variants: _,
fields: _,
largest_niche: _,
} = layout;
let rustc_target::abi::Layout { size, align, abi: _, variants: _, fields: _, largest_niche: _ } =
layout;
let (kind, extra) = match *place.inner() {
CPlaceInner::Var(place_local, var) => {
@ -91,10 +81,7 @@ pub(super) fn add_local_place_comments<'tcx>(
}
CPlaceInner::VarPair(place_local, var1, var2) => {
assert_eq!(local, place_local);
(
"ssa",
Cow::Owned(format!(",var=({}, {})", var1.index(), var2.index())),
)
("ssa", Cow::Owned(format!(",var=({}, {})", var1.index(), var2.index())))
}
CPlaceInner::VarLane(_local, _var, _lane) => unreachable!(),
CPlaceInner::Addr(ptr, meta) => {
@ -104,18 +91,15 @@ pub(super) fn add_local_place_comments<'tcx>(
Cow::Borrowed("")
};
match ptr.base_and_offset() {
(crate::pointer::PointerBase::Addr(addr), offset) => (
"reuse",
format!("storage={}{}{}", addr, offset, meta).into(),
),
(crate::pointer::PointerBase::Stack(stack_slot), offset) => (
"stack",
format!("storage={}{}{}", stack_slot, offset, meta).into(),
),
(crate::pointer::PointerBase::Dangling(align), offset) => (
"zst",
format!("align={},offset={}", align.bytes(), offset).into(),
),
(crate::pointer::PointerBase::Addr(addr), offset) => {
("reuse", format!("storage={}{}{}", addr, offset, meta).into())
}
(crate::pointer::PointerBase::Stack(stack_slot), offset) => {
("stack", format!("storage={}{}{}", stack_slot, offset, meta).into())
}
(crate::pointer::PointerBase::Dangling(align), offset) => {
("zst", format!("align={},offset={}", align.bytes(), offset).into())
}
}
}
};
@ -128,11 +112,7 @@ pub(super) fn add_local_place_comments<'tcx>(
size.bytes(),
align.abi.bytes(),
align.pref.bytes(),
if extra.is_empty() {
""
} else {
" "
},
if extra.is_empty() { "" } else { " " },
extra,
));
}

View file

@ -38,25 +38,15 @@ fn clif_sig_from_fn_abi<'tcx>(
| Conv::X86VectorCall
| Conv::AmdGpuKernel
| Conv::AvrInterrupt
| Conv::AvrNonBlockingInterrupt => {
todo!("{:?}", fn_abi.conv)
}
| Conv::AvrNonBlockingInterrupt => todo!("{:?}", fn_abi.conv),
};
let inputs = fn_abi
.args
.iter()
.map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter())
.flatten();
let inputs = fn_abi.args.iter().map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()).flatten();
let (return_ptr, returns) = fn_abi.ret.get_abi_return(tcx);
// Sometimes the first param is an pointer to the place where the return value needs to be stored.
let params: Vec<_> = return_ptr.into_iter().chain(inputs).collect();
Signature {
params,
returns,
call_conv,
}
Signature { params, returns, call_conv }
}
pub(crate) fn get_function_sig<'tcx>(
@ -65,34 +55,25 @@ pub(crate) fn get_function_sig<'tcx>(
inst: Instance<'tcx>,
) -> Signature {
assert!(!inst.substs.needs_infer());
clif_sig_from_fn_abi(
tcx,
triple,
&FnAbi::of_instance(&RevealAllLayoutCx(tcx), inst, &[]),
)
clif_sig_from_fn_abi(tcx, triple, &FnAbi::of_instance(&RevealAllLayoutCx(tcx), inst, &[]))
}
/// Instance must be monomorphized
pub(crate) fn import_function<'tcx>(
tcx: TyCtxt<'tcx>,
module: &mut impl Module,
module: &mut dyn Module,
inst: Instance<'tcx>,
) -> FuncId {
let name = tcx.symbol_name(inst).name.to_string();
let sig = get_function_sig(tcx, module.isa().triple(), inst);
module
.declare_function(&name, Linkage::Import, &sig)
.unwrap()
module.declare_function(&name, Linkage::Import, &sig).unwrap()
}
impl<'tcx, M: Module> FunctionCx<'_, 'tcx, M> {
impl<'tcx> FunctionCx<'_, '_, 'tcx> {
/// Instance must be monomorphized
pub(crate) fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef {
let func_id = import_function(self.tcx, &mut self.cx.module, inst);
let func_ref = self
.cx
.module
.declare_func_in_func(func_id, &mut self.bcx.func);
let func_id = import_function(self.tcx, self.cx.module, inst);
let func_ref = self.cx.module.declare_func_in_func(func_id, &mut self.bcx.func);
#[cfg(debug_assertions)]
self.add_comment(func_ref, format!("{:?}", inst));
@ -107,20 +88,9 @@ impl<'tcx, M: Module> FunctionCx<'_, 'tcx, M> {
returns: Vec<AbiParam>,
args: &[Value],
) -> &[Value] {
let sig = Signature {
params,
returns,
call_conv: CallConv::triple_default(self.triple()),
};
let func_id = self
.cx
.module
.declare_function(&name, Linkage::Import, &sig)
.unwrap();
let func_ref = self
.cx
.module
.declare_func_in_func(func_id, &mut self.bcx.func);
let sig = Signature { params, returns, call_conv: CallConv::triple_default(self.triple()) };
let func_id = self.cx.module.declare_function(&name, Linkage::Import, &sig).unwrap();
let func_ref = self.cx.module.declare_func_in_func(func_id, &mut self.bcx.func);
let call_inst = self.bcx.ins().call(func_ref, args);
#[cfg(debug_assertions)]
{
@ -140,17 +110,12 @@ impl<'tcx, M: Module> FunctionCx<'_, 'tcx, M> {
let (input_tys, args): (Vec<_>, Vec<_>) = args
.iter()
.map(|arg| {
(
AbiParam::new(self.clif_type(arg.layout().ty).unwrap()),
arg.load_scalar(self),
)
(AbiParam::new(self.clif_type(arg.layout().ty).unwrap()), arg.load_scalar(self))
})
.unzip();
let return_layout = self.layout_of(return_ty);
let return_tys = if let ty::Tuple(tup) = return_ty.kind() {
tup.types()
.map(|ty| AbiParam::new(self.clif_type(ty).unwrap()))
.collect()
tup.types().map(|ty| AbiParam::new(self.clif_type(ty).unwrap())).collect()
} else {
vec![AbiParam::new(self.clif_type(return_ty).unwrap())]
};
@ -169,7 +134,7 @@ impl<'tcx, M: Module> FunctionCx<'_, 'tcx, M> {
/// Make a [`CPlace`] capable of holding value of the specified type.
fn make_local_place<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
fx: &mut FunctionCx<'_, '_, 'tcx>,
local: Local,
layout: TyAndLayout<'tcx>,
is_ssa: bool,
@ -190,10 +155,7 @@ fn make_local_place<'tcx>(
place
}
pub(crate) fn codegen_fn_prelude<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
start_block: Block,
) {
pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_block: Block) {
fx.bcx.append_block_params_for_function_params(start_block);
fx.bcx.switch_to_block(start_block);
@ -204,13 +166,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(
#[cfg(debug_assertions)]
self::comments::add_args_header_comment(fx);
let mut block_params_iter = fx
.bcx
.func
.dfg
.block_params(start_block)
.to_vec()
.into_iter();
let mut block_params_iter = fx.bcx.func.dfg.block_params(start_block).to_vec().into_iter();
let ret_place =
self::returning::codegen_return_param(fx, &ssa_analyzed, &mut block_params_iter);
assert_eq!(fx.local_map.push(ret_place), RETURN_PLACE);
@ -286,10 +242,10 @@ pub(crate) fn codegen_fn_prelude<'tcx>(
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(
fx.tcx.at(local_decl.source_info.span),
ParamEnv::reveal_all(),
);
let internally_mutable = !val
.layout()
.ty
.is_freeze(fx.tcx.at(local_decl.source_info.span), ParamEnv::reveal_all());
if local_decl.mutability == mir::Mutability::Not && !internally_mutable {
// We wont mutate this argument, so it is fine to borrow the backing storage
// of this argument, to prevent a copy.
@ -321,9 +277,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(
ArgKind::Spread(params) => {
for (i, param) in params.into_iter().enumerate() {
if let Some(param) = param {
place
.place_field(fx, mir::Field::new(i))
.write_cvalue(fx, param);
place.place_field(fx, mir::Field::new(i)).write_cvalue(fx, param);
}
}
}
@ -340,13 +294,11 @@ pub(crate) fn codegen_fn_prelude<'tcx>(
assert_eq!(fx.local_map.push(place), local);
}
fx.bcx
.ins()
.jump(*fx.block_map.get(START_BLOCK).unwrap(), &[]);
fx.bcx.ins().jump(*fx.block_map.get(START_BLOCK).unwrap(), &[]);
}
pub(crate) fn codegen_terminator_call<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
fx: &mut FunctionCx<'_, '_, 'tcx>,
span: Span,
current_block: Block,
func: &Operand<'tcx>,
@ -354,9 +306,8 @@ pub(crate) fn codegen_terminator_call<'tcx>(
destination: Option<(Place<'tcx>, BasicBlock)>,
) {
let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx));
let fn_sig = fx
.tcx
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
let fn_sig =
fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
let destination = destination.map(|(place, bb)| (codegen_place(fx, place), bb));
@ -404,20 +355,11 @@ pub(crate) fn codegen_terminator_call<'tcx>(
let fn_abi = if let Some(instance) = instance {
FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), instance, &extra_args)
} else {
FnAbi::of_fn_ptr(
&RevealAllLayoutCx(fx.tcx),
fn_ty.fn_sig(fx.tcx),
&extra_args,
)
FnAbi::of_fn_ptr(&RevealAllLayoutCx(fx.tcx), fn_ty.fn_sig(fx.tcx), &extra_args)
};
let is_cold = instance
.map(|inst| {
fx.tcx
.codegen_fn_attrs(inst.def_id())
.flags
.contains(CodegenFnAttrFlags::COLD)
})
.map(|inst| fx.tcx.codegen_fn_attrs(inst.def_id()).flags.contains(CodegenFnAttrFlags::COLD))
.unwrap_or(false);
if is_cold {
fx.cold_blocks.insert(current_block);
@ -441,9 +383,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
}
args
} else {
args.iter()
.map(|arg| codegen_operand(fx, arg))
.collect::<Vec<_>>()
args.iter().map(|arg| codegen_operand(fx, arg)).collect::<Vec<_>>()
};
// | indirect call target
@ -451,10 +391,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
// v v
let (func_ref, first_arg) = match instance {
// Trait object call
Some(Instance {
def: InstanceDef::Virtual(_, idx),
..
}) => {
Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => {
#[cfg(debug_assertions)]
{
let nop_inst = fx.bcx.ins().nop();
@ -511,10 +448,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
)
.collect::<Vec<_>>();
if instance
.map(|inst| inst.def.requires_caller_location(fx.tcx))
.unwrap_or(false)
{
if instance.map(|inst| inst.def.requires_caller_location(fx.tcx)).unwrap_or(false) {
// Pass the caller location for `#[track_caller]`.
let caller_location = fx.get_caller_location(span);
call_args.extend(
@ -543,10 +477,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
// FIXME find a cleaner way to support varargs
if fn_sig.c_variadic {
if fn_sig.abi != Abi::C {
fx.tcx.sess.span_fatal(
span,
&format!("Variadic call for non-C abi {:?}", fn_sig.abi),
);
fx.tcx.sess.span_fatal(span, &format!("Variadic call for non-C abi {:?}", fn_sig.abi));
}
let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
let abi_params = call_args
@ -555,9 +486,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
let ty = fx.bcx.func.dfg.value_type(arg);
if !ty.is_int() {
// FIXME set %al to upperbound on float args once floats are supported
fx.tcx
.sess
.span_fatal(span, &format!("Non int ty {:?} for variadic call", ty));
fx.tcx.sess.span_fatal(span, &format!("Non int ty {:?} for variadic call", ty));
}
AbiParam::new(ty)
})
@ -574,7 +503,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
}
pub(crate) fn codegen_drop<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
fx: &mut FunctionCx<'_, '_, 'tcx>,
span: Span,
drop_place: CPlace<'tcx>,
) {
@ -611,10 +540,7 @@ pub(crate) fn codegen_drop<'tcx>(
fx,
fx.layout_of(fx.tcx.mk_ref(
&ty::RegionKind::ReErased,
TypeAndMut {
ty,
mutbl: crate::rustc_hir::Mutability::Mut,
},
TypeAndMut { ty, mutbl: crate::rustc_hir::Mutability::Mut },
)),
);
let arg_value = adjust_arg_for_abi(fx, arg_value, &fn_abi.args[0]);

View file

@ -71,12 +71,7 @@ fn cast_target_to_abi_params(cast: CastTarget) -> SmallVec<[AbiParam; 2]> {
.prefix
.iter()
.flatten()
.map(|&kind| {
reg_to_abi_param(Reg {
kind,
size: cast.prefix_chunk_size,
})
})
.map(|&kind| reg_to_abi_param(Reg { kind, size: cast.prefix_chunk_size }))
.chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit)))
.collect::<SmallVec<_>>();
@ -98,12 +93,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
match self.mode {
PassMode::Ignore => smallvec![],
PassMode::Direct(attrs) => match &self.layout.abi {
Abi::Scalar(scalar) => {
smallvec![apply_arg_attrs_to_abi_param(
AbiParam::new(scalar_to_clif_type(tcx, scalar.clone())),
attrs
)]
}
Abi::Scalar(scalar) => smallvec![apply_arg_attrs_to_abi_param(
AbiParam::new(scalar_to_clif_type(tcx, scalar.clone())),
attrs
)],
Abi::Vector { .. } => {
let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout).unwrap();
smallvec![AbiParam::new(vector_ty)]
@ -122,11 +115,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
_ => unreachable!("{:?}", self.layout.abi),
},
PassMode::Cast(cast) => cast_target_to_abi_params(cast),
PassMode::Indirect {
attrs,
extra_attrs: None,
on_stack,
} => {
PassMode::Indirect { attrs, extra_attrs: None, on_stack } => {
if on_stack {
let size = u32::try_from(self.layout.size.bytes()).unwrap();
smallvec![apply_arg_attrs_to_abi_param(
@ -134,17 +123,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
attrs
)]
} else {
smallvec![apply_arg_attrs_to_abi_param(
AbiParam::new(pointer_ty(tcx)),
attrs
)]
smallvec![apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs)]
}
}
PassMode::Indirect {
attrs,
extra_attrs: Some(extra_attrs),
on_stack,
} => {
PassMode::Indirect { attrs, extra_attrs: Some(extra_attrs), on_stack } => {
assert!(!on_stack);
smallvec![
apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs),
@ -158,10 +140,9 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
match self.mode {
PassMode::Ignore => (None, vec![]),
PassMode::Direct(_) => match &self.layout.abi {
Abi::Scalar(scalar) => (
None,
vec![AbiParam::new(scalar_to_clif_type(tcx, scalar.clone()))],
),
Abi::Scalar(scalar) => {
(None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar.clone()))])
}
Abi::Vector { .. } => {
let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout).unwrap();
(None, vec![AbiParam::new(vector_ty)])
@ -177,31 +158,19 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
_ => unreachable!("{:?}", self.layout.abi),
},
PassMode::Cast(cast) => (None, cast_target_to_abi_params(cast).into_iter().collect()),
PassMode::Indirect {
attrs: _,
extra_attrs: None,
on_stack,
} => {
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack } => {
assert!(!on_stack);
(
Some(AbiParam::special(
pointer_ty(tcx),
ArgumentPurpose::StructReturn,
)),
vec![],
)
(Some(AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructReturn)), vec![])
}
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value")
}
PassMode::Indirect {
attrs: _,
extra_attrs: Some(_),
on_stack: _,
} => unreachable!("unsized return value"),
}
}
}
pub(super) fn to_casted_value<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
fx: &mut FunctionCx<'_, '_, 'tcx>,
arg: CValue<'tcx>,
cast: CastTarget,
) -> SmallVec<[Value; 2]> {
@ -211,9 +180,7 @@ pub(super) fn to_casted_value<'tcx>(
cast_target_to_abi_params(cast)
.into_iter()
.map(|param| {
let val = ptr
.offset_i64(fx, offset)
.load(fx, param.value_type, MemFlags::new());
let val = ptr.offset_i64(fx, offset).load(fx, param.value_type, MemFlags::new());
offset += i64::from(param.value_type.bytes());
val
})
@ -221,16 +188,13 @@ pub(super) fn to_casted_value<'tcx>(
}
pub(super) fn from_casted_value<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
fx: &mut FunctionCx<'_, '_, 'tcx>,
block_params: &[Value],
layout: TyAndLayout<'tcx>,
cast: CastTarget,
) -> CValue<'tcx> {
let abi_params = cast_target_to_abi_params(cast);
let abi_param_size: u32 = abi_params
.iter()
.map(|param| param.value_type.bytes())
.sum();
let abi_param_size: u32 = abi_params.iter().map(|param| param.value_type.bytes()).sum();
let layout_size = u32::try_from(layout.size.bytes()).unwrap();
let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
kind: StackSlotKind::ExplicitSlot,
@ -260,7 +224,7 @@ pub(super) fn from_casted_value<'tcx>(
/// Get a set of values to be passed as function arguments.
pub(super) fn adjust_arg_for_abi<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
fx: &mut FunctionCx<'_, '_, 'tcx>,
arg: CValue<'tcx>,
arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
) -> SmallVec<[Value; 2]> {
@ -283,7 +247,7 @@ pub(super) fn adjust_arg_for_abi<'tcx>(
/// Create a [`CValue`] containing the value of a function parameter adding clif function parameters
/// as necessary.
pub(super) fn cvalue_for_param<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
fx: &mut FunctionCx<'_, '_, 'tcx>,
#[cfg_attr(not(debug_assertions), allow(unused_variables))] local: Option<mir::Local>,
#[cfg_attr(not(debug_assertions), allow(unused_variables))] local_field: Option<usize>,
arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
@ -294,10 +258,7 @@ pub(super) fn cvalue_for_param<'tcx>(
.into_iter()
.map(|abi_param| {
let block_param = block_params_iter.next().unwrap();
assert_eq!(
fx.bcx.func.dfg.value_type(block_param),
abi_param.value_type
);
assert_eq!(fx.bcx.func.dfg.value_type(block_param), abi_param.value_type);
block_param
})
.collect::<SmallVec<[_; 2]>>();
@ -321,29 +282,14 @@ pub(super) fn cvalue_for_param<'tcx>(
}
PassMode::Pair(_, _) => {
assert_eq!(block_params.len(), 2, "{:?}", block_params);
Some(CValue::by_val_pair(
block_params[0],
block_params[1],
arg_abi.layout,
))
Some(CValue::by_val_pair(block_params[0], block_params[1], arg_abi.layout))
}
PassMode::Cast(cast) => Some(from_casted_value(fx, &block_params, arg_abi.layout, cast)),
PassMode::Indirect {
attrs: _,
extra_attrs: None,
on_stack: _,
} => {
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
assert_eq!(block_params.len(), 1, "{:?}", block_params);
Some(CValue::by_ref(
Pointer::new(block_params[0]),
arg_abi.layout,
))
Some(CValue::by_ref(Pointer::new(block_params[0]), arg_abi.layout))
}
PassMode::Indirect {
attrs: _,
extra_attrs: Some(_),
on_stack: _,
} => {
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
assert_eq!(block_params.len(), 2, "{:?}", block_params);
Some(CValue::by_ref_unsized(
Pointer::new(block_params[0]),

View file

@ -8,14 +8,13 @@ use smallvec::{smallvec, SmallVec};
/// Can the given type be returned into an ssa var or does it need to be returned on the stack.
pub(crate) fn can_return_to_ssa_var<'tcx>(
fx: &FunctionCx<'_, 'tcx, impl Module>,
fx: &FunctionCx<'_, '_, 'tcx>,
func: &mir::Operand<'tcx>,
args: &[mir::Operand<'tcx>],
) -> bool {
let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx));
let fn_sig = fx
.tcx
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
let fn_sig =
fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
// Handle special calls like instrinsics and empty drop glue.
let instance = if let ty::FnDef(def_id, substs) = *fn_ty.kind() {
@ -42,11 +41,7 @@ pub(crate) fn can_return_to_ssa_var<'tcx>(
let fn_abi = if let Some(instance) = instance {
FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), instance, &extra_args)
} else {
FnAbi::of_fn_ptr(
&RevealAllLayoutCx(fx.tcx),
fn_ty.fn_sig(fx.tcx),
&extra_args,
)
FnAbi::of_fn_ptr(&RevealAllLayoutCx(fx.tcx), fn_ty.fn_sig(fx.tcx), &extra_args)
};
match fn_abi.ret.mode {
PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) => true,
@ -58,15 +53,12 @@ pub(crate) fn can_return_to_ssa_var<'tcx>(
/// Return a place where the return value of the current function can be written to. If necessary
/// this adds an extra parameter pointing to where the return value needs to be stored.
pub(super) fn codegen_return_param<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
fx: &mut FunctionCx<'_, '_, 'tcx>,
ssa_analyzed: &rustc_index::vec::IndexVec<Local, crate::analyze::SsaKind>,
block_params_iter: &mut impl Iterator<Item = Value>,
) -> CPlace<'tcx> {
let (ret_place, ret_param): (_, SmallVec<[_; 2]>) = match fx.fn_abi.as_ref().unwrap().ret.mode {
PassMode::Ignore => (
CPlace::no_place(fx.fn_abi.as_ref().unwrap().ret.layout),
smallvec![],
),
PassMode::Ignore => (CPlace::no_place(fx.fn_abi.as_ref().unwrap().ret.layout), smallvec![]),
PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(_) => {
let is_ssa = ssa_analyzed[RETURN_PLACE] == crate::analyze::SsaKind::Ssa;
(
@ -79,26 +71,17 @@ pub(super) fn codegen_return_param<'tcx>(
smallvec![],
)
}
PassMode::Indirect {
attrs: _,
extra_attrs: None,
on_stack: _,
} => {
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
let ret_param = block_params_iter.next().unwrap();
assert_eq!(fx.bcx.func.dfg.value_type(ret_param), pointer_ty(fx.tcx));
(
CPlace::for_ptr(
Pointer::new(ret_param),
fx.fn_abi.as_ref().unwrap().ret.layout,
),
CPlace::for_ptr(Pointer::new(ret_param), fx.fn_abi.as_ref().unwrap().ret.layout),
smallvec![ret_param],
)
}
PassMode::Indirect {
attrs: _,
extra_attrs: Some(_),
on_stack: _,
} => unreachable!("unsized return value"),
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value")
}
};
#[cfg(not(debug_assertions))]
@ -120,27 +103,21 @@ pub(super) fn codegen_return_param<'tcx>(
/// Invokes the closure with if necessary a value representing the return pointer. When the closure
/// returns the call return value(s) if any are written to the correct place.
pub(super) fn codegen_with_call_return_arg<'tcx, M: Module, T>(
fx: &mut FunctionCx<'_, 'tcx, M>,
pub(super) fn codegen_with_call_return_arg<'tcx, T>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
ret_arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
ret_place: Option<CPlace<'tcx>>,
f: impl FnOnce(&mut FunctionCx<'_, 'tcx, M>, Option<Value>) -> (Inst, T),
f: impl FnOnce(&mut FunctionCx<'_, '_, 'tcx>, Option<Value>) -> (Inst, T),
) -> (Inst, T) {
let return_ptr = match ret_arg_abi.mode {
PassMode::Ignore => None,
PassMode::Indirect {
attrs: _,
extra_attrs: None,
on_stack: _,
} => match ret_place {
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => match ret_place {
Some(ret_place) => Some(ret_place.to_ptr().get_addr(fx)),
None => Some(fx.bcx.ins().iconst(fx.pointer_type, 43)), // FIXME allocate temp stack slot
},
PassMode::Indirect {
attrs: _,
extra_attrs: Some(_),
on_stack: _,
} => unreachable!("unsized return value"),
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value")
}
PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(_) => None,
};
@ -177,37 +154,24 @@ pub(super) fn codegen_with_call_return_arg<'tcx, M: Module, T>(
ret_place.write_cvalue(fx, result);
}
}
PassMode::Indirect {
attrs: _,
extra_attrs: None,
on_stack: _,
} => {}
PassMode::Indirect {
attrs: _,
extra_attrs: Some(_),
on_stack: _,
} => unreachable!("unsized return value"),
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {}
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value")
}
}
(call_inst, meta)
}
/// Codegen a return instruction with the right return value(s) if any.
pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, impl Module>) {
pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, '_>) {
match fx.fn_abi.as_ref().unwrap().ret.mode {
PassMode::Ignore
| PassMode::Indirect {
attrs: _,
extra_attrs: None,
on_stack: _,
} => {
PassMode::Ignore | PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
fx.bcx.ins().return_(&[]);
}
PassMode::Indirect {
attrs: _,
extra_attrs: Some(_),
on_stack: _,
} => unreachable!("unsized return value"),
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value")
}
PassMode::Direct(_) => {
let place = fx.get_local_place(RETURN_PLACE);
let ret_val = place.to_cvalue(fx).load_scalar(fx);