Merge commit '9a0c32934e
' into sync_cg_clif-2021-03-05
This commit is contained in:
commit
7a6ea77473
73 changed files with 1145 additions and 2596 deletions
|
@ -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,
|
||||
));
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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]),
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue