Replace EmptySinglePair with SmallVec
This commit is contained in:
parent
fc595f1a55
commit
d263447878
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -333,6 +333,7 @@ dependencies = [
|
||||
"indexmap",
|
||||
"libloading",
|
||||
"object",
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
|
@ -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/"]
|
||||
|
@ -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);
|
||||
|
@ -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![]),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
@ -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,
|
||||
))
|
||||
}
|
||||
|
@ -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,
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user