This commit is contained in:
bjorn3 2023-09-19 12:25:47 +00:00
commit 5f3b867831
6 changed files with 45 additions and 62 deletions

View File

@ -100,11 +100,11 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
} }
_ => unreachable!("{:?}", self.layout.abi), _ => unreachable!("{:?}", self.layout.abi),
}, },
PassMode::Cast(ref cast, pad_i32) => { PassMode::Cast { ref cast, pad_i32 } => {
assert!(!pad_i32, "padding support not yet implemented"); assert!(!pad_i32, "padding support not yet implemented");
cast_target_to_abi_params(cast) cast_target_to_abi_params(cast)
} }
PassMode::Indirect { attrs, extra_attrs: None, on_stack } => { PassMode::Indirect { attrs, meta_attrs: None, on_stack } => {
if on_stack { if on_stack {
// Abi requires aligning struct size to pointer size // Abi requires aligning struct size to pointer size
let size = self.layout.size.align_to(tcx.data_layout.pointer_align.abi); let size = self.layout.size.align_to(tcx.data_layout.pointer_align.abi);
@ -117,11 +117,11 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
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, meta_attrs: Some(meta_attrs), on_stack } => {
assert!(!on_stack); assert!(!on_stack);
smallvec![ smallvec![
apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs), apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs),
apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), extra_attrs), apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), meta_attrs),
] ]
} }
} }
@ -148,14 +148,14 @@ fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option<AbiParam>, Vec<AbiParam>)
} }
_ => unreachable!("{:?}", self.layout.abi), _ => unreachable!("{:?}", self.layout.abi),
}, },
PassMode::Cast(ref cast, _) => { PassMode::Cast { ref cast, .. } => {
(None, cast_target_to_abi_params(cast).into_iter().collect()) (None, cast_target_to_abi_params(cast).into_iter().collect())
} }
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack } => { PassMode::Indirect { attrs: _, meta_attrs: None, on_stack } => {
assert!(!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: _ } => { PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value") unreachable!("unsized return value")
} }
} }
@ -229,7 +229,7 @@ pub(super) fn adjust_arg_for_abi<'tcx>(
let (a, b) = arg.load_scalar_pair(fx); let (a, b) = arg.load_scalar_pair(fx);
smallvec![a, b] smallvec![a, b]
} }
PassMode::Cast(ref cast, _) => to_casted_value(fx, arg, cast), PassMode::Cast { ref cast, .. } => to_casted_value(fx, arg, cast),
PassMode::Indirect { .. } => { PassMode::Indirect { .. } => {
if is_owned { if is_owned {
match arg.force_stack(fx) { match arg.force_stack(fx) {
@ -287,14 +287,14 @@ pub(super) fn cvalue_for_param<'tcx>(
assert_eq!(block_params.len(), 2, "{:?}", block_params); 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(ref cast, _) => { PassMode::Cast { ref cast, .. } => {
Some(from_casted_value(fx, &block_params, arg_abi.layout, cast)) Some(from_casted_value(fx, &block_params, arg_abi.layout, cast))
} }
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
assert_eq!(block_params.len(), 1, "{:?}", block_params); 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: _, meta_attrs: Some(_), on_stack: _ } => {
assert_eq!(block_params.len(), 2, "{:?}", block_params); assert_eq!(block_params.len(), 2, "{:?}", block_params);
Some(CValue::by_ref_unsized( Some(CValue::by_ref_unsized(
Pointer::new(block_params[0]), Pointer::new(block_params[0]),

View File

@ -13,7 +13,7 @@ pub(super) fn codegen_return_param<'tcx>(
block_params_iter: &mut impl Iterator<Item = Value>, block_params_iter: &mut impl Iterator<Item = Value>,
) -> CPlace<'tcx> { ) -> CPlace<'tcx> {
let (ret_place, ret_param): (_, SmallVec<[_; 2]>) = 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 | PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(..) => { PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast { .. } => {
let is_ssa = let is_ssa =
ssa_analyzed[RETURN_PLACE].is_ssa(fx, fx.fn_abi.as_ref().unwrap().ret.layout.ty); ssa_analyzed[RETURN_PLACE].is_ssa(fx, fx.fn_abi.as_ref().unwrap().ret.layout.ty);
( (
@ -26,7 +26,7 @@ pub(super) fn codegen_return_param<'tcx>(
smallvec![], smallvec![],
) )
} }
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
let ret_param = block_params_iter.next().unwrap(); let ret_param = block_params_iter.next().unwrap();
assert_eq!(fx.bcx.func.dfg.value_type(ret_param), fx.pointer_type); assert_eq!(fx.bcx.func.dfg.value_type(ret_param), fx.pointer_type);
( (
@ -34,7 +34,7 @@ pub(super) fn codegen_return_param<'tcx>(
smallvec![ret_param], smallvec![ret_param],
) )
} }
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => { PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value") unreachable!("unsized return value")
} }
}; };
@ -62,7 +62,7 @@ pub(super) fn codegen_with_call_return_arg<'tcx>(
) { ) {
let (ret_temp_place, return_ptr) = match ret_arg_abi.mode { let (ret_temp_place, return_ptr) = match ret_arg_abi.mode {
PassMode::Ignore => (None, None), PassMode::Ignore => (None, None),
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
if let Some(ret_ptr) = ret_place.try_to_ptr() { if let Some(ret_ptr) = ret_place.try_to_ptr() {
// This is an optimization to prevent unnecessary copies of the return value when // This is an optimization to prevent unnecessary copies of the return value when
// the return place is already a memory place as opposed to a register. // the return place is already a memory place as opposed to a register.
@ -73,10 +73,10 @@ pub(super) fn codegen_with_call_return_arg<'tcx>(
(Some(place), Some(place.to_ptr().get_addr(fx))) (Some(place), Some(place.to_ptr().get_addr(fx)))
} }
} }
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => { PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value") unreachable!("unsized return value")
} }
PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(..) => (None, None), PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast { .. } => (None, None),
}; };
let call_inst = f(fx, return_ptr); let call_inst = f(fx, return_ptr);
@ -93,21 +93,21 @@ pub(super) fn codegen_with_call_return_arg<'tcx>(
ret_place ret_place
.write_cvalue(fx, CValue::by_val_pair(ret_val_a, ret_val_b, ret_arg_abi.layout)); .write_cvalue(fx, CValue::by_val_pair(ret_val_a, ret_val_b, ret_arg_abi.layout));
} }
PassMode::Cast(ref cast, _) => { PassMode::Cast { ref cast, .. } => {
let results = let results =
fx.bcx.inst_results(call_inst).iter().copied().collect::<SmallVec<[Value; 2]>>(); fx.bcx.inst_results(call_inst).iter().copied().collect::<SmallVec<[Value; 2]>>();
let result = let result =
super::pass_mode::from_casted_value(fx, &results, ret_place.layout(), cast); super::pass_mode::from_casted_value(fx, &results, ret_place.layout(), cast);
ret_place.write_cvalue(fx, result); ret_place.write_cvalue(fx, result);
} }
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
if let Some(ret_temp_place) = ret_temp_place { if let Some(ret_temp_place) = ret_temp_place {
// If ret_temp_place is None, it is not necessary to copy the return value. // If ret_temp_place is None, it is not necessary to copy the return value.
let ret_temp_value = ret_temp_place.to_cvalue(fx); let ret_temp_value = ret_temp_place.to_cvalue(fx);
ret_place.write_cvalue(fx, ret_temp_value); ret_place.write_cvalue(fx, ret_temp_value);
} }
} }
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => { PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value") unreachable!("unsized return value")
} }
} }
@ -116,10 +116,10 @@ pub(super) fn codegen_with_call_return_arg<'tcx>(
/// Codegen a return instruction with the right return value(s) if any. /// Codegen a return instruction with the right return value(s) if any.
pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, '_>) { pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, '_>) {
match fx.fn_abi.as_ref().unwrap().ret.mode { match fx.fn_abi.as_ref().unwrap().ret.mode {
PassMode::Ignore | PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { PassMode::Ignore | PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
fx.bcx.ins().return_(&[]); fx.bcx.ins().return_(&[]);
} }
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => { PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value") unreachable!("unsized return value")
} }
PassMode::Direct(_) => { PassMode::Direct(_) => {
@ -132,7 +132,7 @@ pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, '_>) {
let (ret_val_a, ret_val_b) = place.to_cvalue(fx).load_scalar_pair(fx); let (ret_val_a, ret_val_b) = place.to_cvalue(fx).load_scalar_pair(fx);
fx.bcx.ins().return_(&[ret_val_a, ret_val_b]); fx.bcx.ins().return_(&[ret_val_a, ret_val_b]);
} }
PassMode::Cast(ref cast, _) => { PassMode::Cast { ref cast, .. } => {
let place = fx.get_local_place(RETURN_PLACE); let place = fx.get_local_place(RETURN_PLACE);
let ret_val = place.to_cvalue(fx); let ret_val = place.to_cvalue(fx);
let ret_vals = super::pass_mode::to_casted_value(fx, ret_val, cast); let ret_vals = super::pass_mode::to_casted_value(fx, ret_val, cast);

View File

@ -249,7 +249,10 @@ pub(crate) fn verify_func(
} }
fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
if !crate::constant::check_constants(fx) { if let Err(err) =
fx.mir.post_mono_checks(fx.tcx, ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c)))
{
err.emit_err(fx.tcx);
fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
// compilation should have been aborted // compilation should have been aborted

View File

@ -3,9 +3,7 @@
use cranelift_module::*; use cranelift_module::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{ use rustc_middle::mir::interpret::{read_target_uint, AllocId, ConstValue, GlobalAlloc, Scalar};
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
};
use crate::prelude::*; use crate::prelude::*;
@ -32,16 +30,6 @@ pub(crate) fn finalize(mut self, tcx: TyCtxt<'_>, module: &mut dyn Module) {
} }
} }
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
let mut all_constants_ok = true;
for constant in &fx.mir.required_consts {
if eval_mir_constant(fx, constant).is_none() {
all_constants_ok = false;
}
}
all_constants_ok
}
pub(crate) fn codegen_static(tcx: TyCtxt<'_>, module: &mut dyn Module, def_id: DefId) { pub(crate) fn codegen_static(tcx: TyCtxt<'_>, module: &mut dyn Module, def_id: DefId) {
let mut constants_cx = ConstantCx::new(); let mut constants_cx = ConstantCx::new();
constants_cx.todo.push(TodoItem::Static(def_id)); constants_cx.todo.push(TodoItem::Static(def_id));
@ -75,30 +63,20 @@ pub(crate) fn codegen_tls_ref<'tcx>(
pub(crate) fn eval_mir_constant<'tcx>( pub(crate) fn eval_mir_constant<'tcx>(
fx: &FunctionCx<'_, '_, 'tcx>, fx: &FunctionCx<'_, '_, 'tcx>,
constant: &Constant<'tcx>, constant: &Constant<'tcx>,
) -> Option<(ConstValue<'tcx>, Ty<'tcx>)> { ) -> (ConstValue<'tcx>, Ty<'tcx>) {
let cv = fx.monomorphize(constant.literal); let cv = fx.monomorphize(constant.literal);
// This cannot fail because we checked all required_consts in advance.
let val = cv let val = cv
.eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(constant.span)) .eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(constant.span))
.map_err(|err| match err { .expect("erroneous constant not captured by required_consts");
ErrorHandled::Reported(_) => { (val, cv.ty())
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
}
ErrorHandled::TooGeneric => {
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
}
})
.ok();
val.map(|val| (val, cv.ty()))
} }
pub(crate) fn codegen_constant_operand<'tcx>( pub(crate) fn codegen_constant_operand<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>, fx: &mut FunctionCx<'_, '_, 'tcx>,
constant: &Constant<'tcx>, constant: &Constant<'tcx>,
) -> CValue<'tcx> { ) -> CValue<'tcx> {
let (const_val, ty) = eval_mir_constant(fx, constant).unwrap_or_else(|| { let (const_val, ty) = eval_mir_constant(fx, constant);
span_bug!(constant.span, "erroneous constant not captured by required_consts")
});
codegen_const_value(fx, const_val, ty) codegen_const_value(fx, const_val, ty)
} }
@ -115,7 +93,7 @@ pub(crate) fn codegen_const_value<'tcx>(
} }
match const_val { match const_val {
ConstValue::ZeroSized => unreachable!(), // we already handles ZST above ConstValue::ZeroSized => unreachable!(), // we already handled ZST above
ConstValue::Scalar(x) => match x { ConstValue::Scalar(x) => match x {
Scalar::Int(int) => { Scalar::Int(int) => {
if fx.clif_type(layout.ty).is_some() { if fx.clif_type(layout.ty).is_some() {
@ -199,13 +177,14 @@ pub(crate) fn codegen_const_value<'tcx>(
CValue::by_val(val, layout) CValue::by_val(val, layout)
} }
}, },
ConstValue::ByRef { alloc, offset } => CValue::by_ref( ConstValue::Indirect { alloc_id, offset } => CValue::by_ref(
pointer_for_allocation(fx, alloc) pointer_for_allocation(fx, alloc_id)
.offset_i64(fx, i64::try_from(offset.bytes()).unwrap()), .offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
layout, layout,
), ),
ConstValue::Slice { data, start, end } => { ConstValue::Slice { data, start, end } => {
let ptr = pointer_for_allocation(fx, data) let alloc_id = fx.tcx.reserve_and_set_memory_alloc(data);
let ptr = pointer_for_allocation(fx, alloc_id)
.offset_i64(fx, i64::try_from(start).unwrap()) .offset_i64(fx, i64::try_from(start).unwrap())
.get_addr(fx); .get_addr(fx);
let len = fx let len = fx
@ -219,9 +198,9 @@ pub(crate) fn codegen_const_value<'tcx>(
fn pointer_for_allocation<'tcx>( fn pointer_for_allocation<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>, fx: &mut FunctionCx<'_, '_, 'tcx>,
alloc: ConstAllocation<'tcx>, alloc_id: AllocId,
) -> crate::pointer::Pointer { ) -> crate::pointer::Pointer {
let alloc_id = fx.tcx.create_memory_alloc(alloc); let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
let data_id = data_id_for_alloc_id( let data_id = data_id_for_alloc_id(
&mut fx.constants_cx, &mut fx.constants_cx,
&mut *fx.module, &mut *fx.module,
@ -352,6 +331,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
unreachable!() unreachable!()
} }
}; };
// FIXME: should we have a cache so we don't do this multiple times for the same `ConstAllocation`?
let data_id = *cx.anon_allocs.entry(alloc_id).or_insert_with(|| { let data_id = *cx.anon_allocs.entry(alloc_id).or_insert_with(|| {
module.declare_anonymous_data(alloc.inner().mutability.is_mut(), false).unwrap() module.declare_anonymous_data(alloc.inner().mutability.is_mut(), false).unwrap()
}); });
@ -456,7 +436,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
operand: &Operand<'tcx>, operand: &Operand<'tcx>,
) -> Option<ConstValue<'tcx>> { ) -> Option<ConstValue<'tcx>> {
match operand { match operand {
Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).unwrap().0), Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).0),
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored // FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
// inside a temporary before being passed to the intrinsic requiring the const argument. // inside a temporary before being passed to the intrinsic requiring the const argument.
// This code tries to find a single constant defining definition of the referenced local. // This code tries to find a single constant defining definition of the referenced local.

View File

@ -242,8 +242,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
} }
} }
InlineAsmOperand::Const { ref value } => { InlineAsmOperand::Const { ref value } => {
let (const_value, ty) = crate::constant::eval_mir_constant(fx, value) let (const_value, ty) = crate::constant::eval_mir_constant(fx, value);
.unwrap_or_else(|| span_bug!(span, "asm const cannot be resolved"));
let value = rustc_codegen_ssa::common::asm_const_to_str( let value = rustc_codegen_ssa::common::asm_const_to_str(
fx.tcx, fx.tcx,
span, span,

View File

@ -176,7 +176,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
}; };
let idx_bytes = match idx_const { let idx_bytes = match idx_const {
ConstValue::ByRef { alloc, offset } => { ConstValue::Indirect { alloc_id, offset } => {
let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
let size = Size::from_bytes( let size = Size::from_bytes(
4 * ret_lane_count, /* size_of([u32; ret_lane_count]) */ 4 * ret_lane_count, /* size_of([u32; ret_lane_count]) */
); );