summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_cranelift/src/value_and_place.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_cranelift/src/value_and_place.rs')
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs115
1 files changed, 83 insertions, 32 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 133c989b6..ff95141ce 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -2,6 +2,8 @@
use crate::prelude::*;
+use rustc_middle::ty::FnSig;
+
use cranelift_codegen::entity::EntityRef;
use cranelift_codegen::ir::immediates::Offset32;
@@ -160,6 +162,7 @@ impl<'tcx> CValue<'tcx> {
}
/// Load a value with layout.abi of scalar
+ #[track_caller]
pub(crate) fn load_scalar(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> Value {
let layout = self.1;
match self.0 {
@@ -182,6 +185,7 @@ impl<'tcx> CValue<'tcx> {
}
/// Load a value pair with layout.abi of scalar pair
+ #[track_caller]
pub(crate) fn load_scalar_pair(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> (Value, Value) {
let layout = self.1;
match self.0 {
@@ -583,17 +587,25 @@ impl<'tcx> CPlace<'tcx> {
let dst_layout = self.layout();
match self.inner {
CPlaceInner::Var(_local, var) => {
- let data = CValue(from.0, dst_layout).load_scalar(fx);
+ let data = match from.1.abi {
+ Abi::Scalar(_) => CValue(from.0, dst_layout).load_scalar(fx),
+ _ => {
+ let (ptr, meta) = from.force_stack(fx);
+ assert!(meta.is_none());
+ CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar(fx)
+ }
+ };
let dst_ty = fx.clif_type(self.layout().ty).unwrap();
transmute_scalar(fx, var, data, dst_ty);
}
CPlaceInner::VarPair(_local, var1, var2) => {
- let (data1, data2) = if from.layout().ty == dst_layout.ty {
- CValue(from.0, dst_layout).load_scalar_pair(fx)
- } else {
- let (ptr, meta) = from.force_stack(fx);
- assert!(meta.is_none());
- CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx)
+ let (data1, data2) = match from.1.abi {
+ Abi::ScalarPair(_, _) => CValue(from.0, dst_layout).load_scalar_pair(fx),
+ _ => {
+ let (ptr, meta) = from.force_stack(fx);
+ assert!(meta.is_none());
+ CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx)
+ }
};
let (dst_ty1, dst_ty2) = fx.clif_pair_type(self.layout().ty).unwrap();
transmute_scalar(fx, var1, data1, dst_ty1);
@@ -607,30 +619,38 @@ impl<'tcx> CPlace<'tcx> {
let mut flags = MemFlags::new();
flags.set_notrap();
- match from.layout().abi {
- Abi::Scalar(_) => {
- let val = from.load_scalar(fx);
- to_ptr.store(fx, val, flags);
- return;
- }
- Abi::ScalarPair(a_scalar, b_scalar) => {
- let (value, extra) = from.load_scalar_pair(fx);
- let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
- to_ptr.store(fx, value, flags);
- to_ptr.offset(fx, b_offset).store(fx, extra, flags);
- return;
- }
- _ => {}
- }
match from.0 {
CValueInner::ByVal(val) => {
to_ptr.store(fx, val, flags);
}
- CValueInner::ByValPair(_, _) => {
- bug!("Non ScalarPair abi {:?} for ByValPair CValue", dst_layout.abi);
- }
+ CValueInner::ByValPair(val1, val2) => match from.layout().abi {
+ Abi::ScalarPair(a_scalar, b_scalar) => {
+ let b_offset =
+ scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
+ to_ptr.store(fx, val1, flags);
+ to_ptr.offset(fx, b_offset).store(fx, val2, flags);
+ }
+ _ => bug!("Non ScalarPair abi {:?} for ByValPair CValue", dst_layout.abi),
+ },
CValueInner::ByRef(from_ptr, None) => {
+ match from.layout().abi {
+ Abi::Scalar(_) => {
+ let val = from.load_scalar(fx);
+ to_ptr.store(fx, val, flags);
+ return;
+ }
+ Abi::ScalarPair(a_scalar, b_scalar) => {
+ let b_offset =
+ scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
+ let (val1, val2) = from.load_scalar_pair(fx);
+ to_ptr.store(fx, val1, flags);
+ to_ptr.offset(fx, b_offset).store(fx, val2, flags);
+ return;
+ }
+ _ => {}
+ }
+
let from_addr = from_ptr.get_addr(fx);
let to_addr = to_ptr.get_addr(fx);
let src_layout = from.1;
@@ -815,11 +835,42 @@ pub(crate) fn assert_assignable<'tcx>(
ParamEnv::reveal_all(),
from_ty.fn_sig(fx.tcx),
);
+ let FnSig {
+ inputs_and_output: types_from,
+ c_variadic: c_variadic_from,
+ unsafety: unsafety_from,
+ abi: abi_from,
+ } = from_sig;
let to_sig = fx
.tcx
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to_ty.fn_sig(fx.tcx));
+ let FnSig {
+ inputs_and_output: types_to,
+ c_variadic: c_variadic_to,
+ unsafety: unsafety_to,
+ abi: abi_to,
+ } = to_sig;
+ let mut types_from = types_from.iter();
+ let mut types_to = types_to.iter();
+ loop {
+ match (types_from.next(), types_to.next()) {
+ (Some(a), Some(b)) => assert_assignable(fx, a, b, limit - 1),
+ (None, None) => break,
+ (Some(_), None) | (None, Some(_)) => panic!("{:#?}/{:#?}", from_ty, to_ty),
+ }
+ }
+ assert_eq!(
+ c_variadic_from, c_variadic_to,
+ "Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}",
+ from_sig, to_sig, fx,
+ );
+ assert_eq!(
+ unsafety_from, unsafety_to,
+ "Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}",
+ from_sig, to_sig, fx,
+ );
assert_eq!(
- from_sig, to_sig,
+ abi_from, abi_to,
"Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}",
from_sig, to_sig, fx,
);
@@ -850,11 +901,11 @@ pub(crate) fn assert_assignable<'tcx>(
}
}
}
- (&ty::Adt(adt_def_a, substs_a), &ty::Adt(adt_def_b, substs_b))
+ (&ty::Adt(adt_def_a, args_a), &ty::Adt(adt_def_b, args_b))
if adt_def_a.did() == adt_def_b.did() =>
{
- let mut types_a = substs_a.types();
- let mut types_b = substs_b.types();
+ let mut types_a = args_a.types();
+ let mut types_b = args_b.types();
loop {
match (types_a.next(), types_b.next()) {
(Some(a), Some(b)) => assert_assignable(fx, a, b, limit - 1),
@@ -864,11 +915,11 @@ pub(crate) fn assert_assignable<'tcx>(
}
}
(ty::Array(a, _), ty::Array(b, _)) => assert_assignable(fx, *a, *b, limit - 1),
- (&ty::Closure(def_id_a, substs_a), &ty::Closure(def_id_b, substs_b))
+ (&ty::Closure(def_id_a, args_a), &ty::Closure(def_id_b, args_b))
if def_id_a == def_id_b =>
{
- let mut types_a = substs_a.types();
- let mut types_b = substs_b.types();
+ let mut types_a = args_a.types();
+ let mut types_b = args_b.types();
loop {
match (types_a.next(), types_b.next()) {
(Some(a), Some(b)) => assert_assignable(fx, a, b, limit - 1),