Replace EmptySinglePair with SmallVec

This commit is contained in:
bjorn3 2021-01-27 10:24:31 +01:00
parent fc595f1a55
commit d263447878
6 changed files with 66 additions and 100 deletions

1
Cargo.lock generated
View File

@ -333,6 +333,7 @@ dependencies = [
"indexmap",
"libloading",
"object",
"smallvec",
"target-lexicon",
]

View File

@ -21,6 +21,7 @@ object = { version = "0.22.0", default-features = false, features = ["std", "rea
ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
indexmap = "1.0.2"
libloading = { version = "0.6.0", optional = true }
smallvec = "1.6.1"
# Uncomment to use local checkout of cranelift
#[patch."https://github.com/bytecodealliance/wasmtime/"]

View File

@ -8,7 +8,6 @@ use rustc_target::abi::call::PassMode;
use cranelift_codegen::entity::EntityRef;
use crate::abi::pass_mode::*;
use crate::prelude::*;
pub(super) fn add_args_header_comment(fx: &mut FunctionCx<'_, '_, impl Module>) {
@ -22,7 +21,7 @@ pub(super) fn add_arg_comment<'tcx>(
kind: &str,
local: Option<mir::Local>,
local_field: Option<usize>,
params: EmptySinglePair<Value>,
params: &[Value],
arg_abi_mode: PassMode,
arg_layout: TyAndLayout<'tcx>,
) {
@ -38,9 +37,17 @@ pub(super) fn add_arg_comment<'tcx>(
};
let params = match params {
Empty => Cow::Borrowed("-"),
Single(param) => Cow::Owned(format!("= {:?}", param)),
Pair(param_a, param_b) => Cow::Owned(format!("= {:?}, {:?}", param_a, param_b)),
[] => Cow::Borrowed("-"),
[param] => Cow::Owned(format!("= {:?}", param)),
[param_a, param_b] => Cow::Owned(format!("= {:?},{:?}", param_a, param_b)),
params => Cow::Owned(format!(
"= {}",
params
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(",")
)),
};
let pass_mode = format!("{:?}", arg_abi_mode);

View File

@ -11,6 +11,7 @@ use rustc_target::abi::call::{Conv, FnAbi};
use rustc_target::spec::abi::Abi;
use cranelift_codegen::ir::AbiParam;
use smallvec::smallvec;
use self::pass_mode::*;
use crate::prelude::*;
@ -534,7 +535,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
);
}
let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0], idx);
(Some(method), Single(ptr))
(Some(method), smallvec![ptr])
}
// Normal call
@ -542,7 +543,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
None,
args.get(0)
.map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0]))
.unwrap_or(Empty),
.unwrap_or(smallvec![]),
),
// Indirect call
@ -557,7 +558,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
Some(func),
args.get(0)
.map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0]))
.unwrap_or(Empty),
.unwrap_or(smallvec![]),
)
}
};

View File

@ -5,78 +5,24 @@ use crate::value_and_place::assert_assignable;
use cranelift_codegen::ir::ArgumentPurpose;
use rustc_target::abi::call::{ArgAbi, PassMode};
pub(super) use EmptySinglePair::*;
#[derive(Copy, Clone, Debug)]
pub(super) enum EmptySinglePair<T> {
Empty,
Single(T),
Pair(T, T),
}
impl<T> EmptySinglePair<T> {
pub(super) fn into_iter(self) -> EmptySinglePairIter<T> {
EmptySinglePairIter(self)
}
pub(super) fn map<U>(self, mut f: impl FnMut(T) -> U) -> EmptySinglePair<U> {
match self {
Empty => Empty,
Single(v) => Single(f(v)),
Pair(a, b) => Pair(f(a), f(b)),
}
}
}
pub(super) struct EmptySinglePairIter<T>(EmptySinglePair<T>);
impl<T> Iterator for EmptySinglePairIter<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
match std::mem::replace(&mut self.0, Empty) {
Empty => None,
Single(v) => Some(v),
Pair(a, b) => {
self.0 = Single(b);
Some(a)
}
}
}
}
impl<T: std::fmt::Debug> EmptySinglePair<T> {
pub(super) fn assert_single(self) -> T {
match self {
Single(v) => v,
_ => panic!("Called assert_single on {:?}", self),
}
}
pub(super) fn assert_pair(self) -> (T, T) {
match self {
Pair(a, b) => (a, b),
_ => panic!("Called assert_pair on {:?}", self),
}
}
}
use smallvec::{smallvec, SmallVec};
pub(super) trait ArgAbiExt<'tcx> {
fn get_abi_param(&self, tcx: TyCtxt<'tcx>) -> EmptySinglePair<AbiParam>;
fn get_abi_param(&self, tcx: TyCtxt<'tcx>) -> SmallVec<[AbiParam; 2]>;
fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option<AbiParam>, Vec<AbiParam>);
}
impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
fn get_abi_param(&self, tcx: TyCtxt<'tcx>) -> EmptySinglePair<AbiParam> {
fn get_abi_param(&self, tcx: TyCtxt<'tcx>) -> SmallVec<[AbiParam; 2]> {
match self.mode {
PassMode::Ignore => EmptySinglePair::Empty,
PassMode::Ignore => smallvec![],
PassMode::Direct(_) => match &self.layout.abi {
Abi::Scalar(scalar) => {
EmptySinglePair::Single(AbiParam::new(scalar_to_clif_type(tcx, scalar.clone())))
smallvec![AbiParam::new(scalar_to_clif_type(tcx, scalar.clone()))]
}
Abi::Vector { .. } => {
let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout).unwrap();
EmptySinglePair::Single(AbiParam::new(vector_ty))
smallvec![AbiParam::new(vector_ty)]
}
_ => unreachable!("{:?}", self.layout.abi),
},
@ -84,11 +30,11 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
Abi::ScalarPair(a, b) => {
let a = scalar_to_clif_type(tcx, a.clone());
let b = scalar_to_clif_type(tcx, b.clone());
EmptySinglePair::Pair(AbiParam::new(a), AbiParam::new(b))
smallvec![AbiParam::new(a), AbiParam::new(b)]
}
_ => unreachable!("{:?}", self.layout.abi),
},
PassMode::Cast(_) => EmptySinglePair::Single(AbiParam::new(pointer_ty(tcx))),
PassMode::Cast(_) => smallvec![AbiParam::new(pointer_ty(tcx))],
PassMode::Indirect {
attrs: _,
extra_attrs: None,
@ -96,12 +42,12 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
} => {
if on_stack {
let size = u32::try_from(self.layout.size.bytes()).unwrap();
EmptySinglePair::Single(AbiParam::special(
smallvec![AbiParam::special(
pointer_ty(tcx),
ArgumentPurpose::StructArgument(size),
))
)]
} else {
EmptySinglePair::Single(AbiParam::new(pointer_ty(tcx)))
smallvec![AbiParam::new(pointer_ty(tcx))]
}
}
PassMode::Indirect {
@ -110,10 +56,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
on_stack,
} => {
assert!(!on_stack);
EmptySinglePair::Pair(
smallvec![
AbiParam::new(pointer_ty(tcx)),
AbiParam::new(pointer_ty(tcx)),
)
]
}
}
}
@ -176,18 +122,18 @@ pub(super) fn adjust_arg_for_abi<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
arg: CValue<'tcx>,
arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
) -> EmptySinglePair<Value> {
) -> SmallVec<[Value; 2]> {
assert_assignable(fx, arg.layout().ty, arg_abi.layout.ty);
match arg_abi.mode {
PassMode::Ignore => Empty,
PassMode::Direct(_) => Single(arg.load_scalar(fx)),
PassMode::Ignore => smallvec![],
PassMode::Direct(_) => smallvec![arg.load_scalar(fx)],
PassMode::Pair(_, _) => {
let (a, b) = arg.load_scalar_pair(fx);
Pair(a, b)
smallvec![a, b]
}
PassMode::Cast(_) | PassMode::Indirect { .. } => match arg.force_stack(fx) {
(ptr, None) => Single(ptr.get_addr(fx)),
(ptr, Some(meta)) => Pair(ptr.get_addr(fx), meta),
(ptr, None) => smallvec![ptr.get_addr(fx)],
(ptr, Some(meta)) => smallvec![ptr.get_addr(fx), meta],
},
}
}
@ -202,8 +148,10 @@ pub(super) fn cvalue_for_param<'tcx>(
arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
) -> Option<CValue<'tcx>> {
let clif_types = arg_abi.get_abi_param(fx.tcx);
let block_params =
clif_types.map(|abi_param| fx.bcx.append_block_param(start_block, abi_param.value_type));
let block_params = clif_types
.into_iter()
.map(|abi_param| fx.bcx.append_block_param(start_block, abi_param.value_type))
.collect::<SmallVec<[_; 2]>>();
#[cfg(debug_assertions)]
crate::abi::comments::add_arg_comment(
@ -211,7 +159,7 @@ pub(super) fn cvalue_for_param<'tcx>(
"arg",
local,
local_field,
block_params,
&block_params,
arg_abi.mode,
arg_abi.layout,
);
@ -219,30 +167,38 @@ pub(super) fn cvalue_for_param<'tcx>(
match arg_abi.mode {
PassMode::Ignore => None,
PassMode::Direct(_) => {
Some(CValue::by_val(block_params.assert_single(), arg_abi.layout))
assert_eq!(block_params.len(), 1, "{:?}", block_params);
Some(CValue::by_val(block_params[0], arg_abi.layout))
}
PassMode::Pair(_, _) => {
let (a, b) = block_params.assert_pair();
Some(CValue::by_val_pair(a, b, arg_abi.layout))
assert_eq!(block_params.len(), 2, "{:?}", block_params);
Some(CValue::by_val_pair(
block_params[0],
block_params[1],
arg_abi.layout,
))
}
PassMode::Cast(_)
| PassMode::Indirect {
attrs: _,
extra_attrs: None,
on_stack: _,
} => Some(CValue::by_ref(
Pointer::new(block_params.assert_single()),
arg_abi.layout,
)),
} => {
assert_eq!(block_params.len(), 1, "{:?}", block_params);
Some(CValue::by_ref(
Pointer::new(block_params[0]),
arg_abi.layout,
))
}
PassMode::Indirect {
attrs: _,
extra_attrs: Some(_),
on_stack: _,
} => {
let (ptr, meta) = block_params.assert_pair();
assert_eq!(block_params.len(), 2, "{:?}", block_params);
Some(CValue::by_ref_unsized(
Pointer::new(ptr),
meta,
Pointer::new(block_params[0]),
block_params[1],
arg_abi.layout,
))
}

View File

@ -1,10 +1,10 @@
//! Return value handling
use crate::abi::pass_mode::*;
use crate::prelude::*;
use rustc_middle::ty::layout::FnAbiExt;
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
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>(
@ -62,10 +62,10 @@ pub(super) fn codegen_return_param<'tcx>(
ssa_analyzed: &rustc_index::vec::IndexVec<Local, crate::analyze::SsaKind>,
start_block: Block,
) -> CPlace<'tcx> {
let (ret_place, ret_param) = match fx.fn_abi.as_ref().unwrap().ret.mode {
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),
Empty,
smallvec![],
),
PassMode::Direct(_) | PassMode::Pair(_, _) => {
let is_ssa = ssa_analyzed[RETURN_PLACE] == crate::analyze::SsaKind::Ssa;
@ -76,7 +76,7 @@ pub(super) fn codegen_return_param<'tcx>(
fx.fn_abi.as_ref().unwrap().ret.layout,
is_ssa,
),
Empty,
smallvec![],
)
}
PassMode::Cast(_)
@ -91,7 +91,7 @@ pub(super) fn codegen_return_param<'tcx>(
Pointer::new(ret_param),
fx.fn_abi.as_ref().unwrap().ret.layout,
),
Single(ret_param),
smallvec![ret_param],
)
}
PassMode::Indirect {
@ -110,7 +110,7 @@ pub(super) fn codegen_return_param<'tcx>(
"ret",
Some(RETURN_PLACE),
None,
ret_param,
&ret_param,
fx.fn_abi.as_ref().unwrap().ret.mode,
fx.fn_abi.as_ref().unwrap().ret.layout,
);