commit
6e2ac83a0c
4 changed files with 106 additions and 23 deletions
43
src/base.rs
43
src/base.rs
|
@ -515,12 +515,43 @@ fn trans_stmt<'tcx>(
|
|||
_ => unreachable!("cast adt {} -> {}", from_ty, to_ty),
|
||||
}
|
||||
|
||||
let discr = crate::discriminant::codegen_get_discriminant(
|
||||
fx,
|
||||
operand,
|
||||
fx.layout_of(to_ty),
|
||||
);
|
||||
lval.write_cvalue(fx, discr);
|
||||
use rustc_target::abi::{TagEncoding, Int, Variants};
|
||||
|
||||
match &operand.layout().variants {
|
||||
Variants::Single { index } => {
|
||||
let discr = operand.layout().ty.discriminant_for_variant(fx.tcx, *index).unwrap();
|
||||
let discr = if discr.ty.is_signed() {
|
||||
rustc_middle::mir::interpret::sign_extend(discr.val, fx.layout_of(discr.ty).size)
|
||||
} else {
|
||||
discr.val
|
||||
};
|
||||
|
||||
let discr = CValue::const_val(fx, fx.layout_of(to_ty), discr);
|
||||
lval.write_cvalue(fx, discr);
|
||||
}
|
||||
Variants::Multiple {
|
||||
tag,
|
||||
tag_field,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
variants: _,
|
||||
} => {
|
||||
let cast_to = fx.clif_type(dest_layout.ty).unwrap();
|
||||
|
||||
// Read the tag/niche-encoded discriminant from memory.
|
||||
let encoded_discr = operand.value_field(fx, mir::Field::new(*tag_field));
|
||||
let encoded_discr = encoded_discr.load_scalar(fx);
|
||||
|
||||
// Decode the discriminant (specifically if it's niche-encoded).
|
||||
let signed = match tag.value {
|
||||
Int(_, signed) => signed,
|
||||
_ => false,
|
||||
};
|
||||
let val = clif_intcast(fx, encoded_discr, cast_to, signed);
|
||||
let val = CValue::by_val(val, dest_layout);
|
||||
lval.write_cvalue(fx, val);
|
||||
}
|
||||
Variants::Multiple { ..} => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
let to_clif_ty = fx.clif_type(to_ty).unwrap();
|
||||
let from = operand.load_scalar(fx);
|
||||
|
|
|
@ -132,7 +132,7 @@ pub(crate) fn trans_const_value<'tcx>(
|
|||
let base_addr = match alloc_kind {
|
||||
Some(GlobalAlloc::Memory(alloc)) => {
|
||||
fx.constants_cx.todo.push(TodoItem::Alloc(ptr.alloc_id));
|
||||
let data_id = data_id_for_alloc_id(fx.module, ptr.alloc_id, alloc.align);
|
||||
let data_id = data_id_for_alloc_id(fx.module, ptr.alloc_id, alloc.align, alloc.mutability);
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
#[cfg(debug_assertions)]
|
||||
fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id));
|
||||
|
@ -182,7 +182,7 @@ fn pointer_for_allocation<'tcx>(
|
|||
) -> crate::pointer::Pointer {
|
||||
let alloc_id = fx.tcx.create_memory_alloc(alloc);
|
||||
fx.constants_cx.todo.push(TodoItem::Alloc(alloc_id));
|
||||
let data_id = data_id_for_alloc_id(fx.module, alloc_id, alloc.align);
|
||||
let data_id = data_id_for_alloc_id(fx.module, alloc_id, alloc.align, alloc.mutability);
|
||||
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -195,12 +195,13 @@ fn data_id_for_alloc_id<B: Backend>(
|
|||
module: &mut Module<B>,
|
||||
alloc_id: AllocId,
|
||||
align: Align,
|
||||
mutability: rustc_hir::Mutability,
|
||||
) -> DataId {
|
||||
module
|
||||
.declare_data(
|
||||
&format!("__alloc_{}", alloc_id.0),
|
||||
Linkage::Local,
|
||||
false,
|
||||
mutability == rustc_hir::Mutability::Mut,
|
||||
false,
|
||||
Some(align.bytes() as u8),
|
||||
)
|
||||
|
@ -271,7 +272,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut Module<impl Backend>, cx: &mu
|
|||
GlobalAlloc::Memory(alloc) => alloc,
|
||||
GlobalAlloc::Function(_) | GlobalAlloc::Static(_) => unreachable!(),
|
||||
};
|
||||
let data_id = data_id_for_alloc_id(module, alloc_id, alloc.align);
|
||||
let data_id = data_id_for_alloc_id(module, alloc_id, alloc.align, alloc.mutability);
|
||||
(data_id, alloc, None)
|
||||
}
|
||||
TodoItem::Static(def_id) => {
|
||||
|
@ -333,9 +334,9 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut Module<impl Backend>, cx: &mu
|
|||
data_ctx.write_function_addr(offset.bytes() as u32, local_func_id);
|
||||
continue;
|
||||
}
|
||||
GlobalAlloc::Memory(_) => {
|
||||
GlobalAlloc::Memory(target_alloc) => {
|
||||
cx.todo.push(TodoItem::Alloc(reloc));
|
||||
data_id_for_alloc_id(module, reloc, alloc.align)
|
||||
data_id_for_alloc_id(module, reloc, target_alloc.align, target_alloc.mutability)
|
||||
}
|
||||
GlobalAlloc::Static(def_id) => {
|
||||
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
|
||||
|
|
|
@ -471,7 +471,26 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
|||
assert_eq!(args.len(), 3);
|
||||
let byte_amount = fx.bcx.ins().imul(count, elem_size);
|
||||
|
||||
if intrinsic.ends_with("_nonoverlapping") {
|
||||
if intrinsic.contains("nonoverlapping") {
|
||||
// FIXME emit_small_memcpy
|
||||
fx.bcx.call_memcpy(fx.module.target_config(), dst, src, byte_amount);
|
||||
} else {
|
||||
// FIXME emit_small_memmove
|
||||
fx.bcx.call_memmove(fx.module.target_config(), dst, src, byte_amount);
|
||||
}
|
||||
};
|
||||
// NOTE: the volatile variants have src and dst swapped
|
||||
volatile_copy_memory | volatile_copy_nonoverlapping_memory, <elem_ty> (v dst, v src, v count) {
|
||||
let elem_size: u64 = fx.layout_of(elem_ty).size.bytes();
|
||||
let elem_size = fx
|
||||
.bcx
|
||||
.ins()
|
||||
.iconst(fx.pointer_type, elem_size as i64);
|
||||
assert_eq!(args.len(), 3);
|
||||
let byte_amount = fx.bcx.ins().imul(count, elem_size);
|
||||
|
||||
// FIXME make the copy actually volatile when using emit_small_mem{cpy,move}
|
||||
if intrinsic.contains("nonoverlapping") {
|
||||
// FIXME emit_small_memcpy
|
||||
fx.bcx.call_memcpy(fx.module.target_config(), dst, src, byte_amount);
|
||||
} else {
|
||||
|
@ -633,11 +652,13 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
|||
transmute, (c from) {
|
||||
ret.write_cvalue_transmute(fx, from);
|
||||
};
|
||||
write_bytes, (c dst, v val, v count) {
|
||||
write_bytes | volatile_set_memory, (c dst, v val, v count) {
|
||||
let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
||||
let count = fx.bcx.ins().imul_imm(count, pointee_size as i64);
|
||||
let dst_ptr = dst.load_scalar(fx);
|
||||
// FIXME make the memset actually volatile when switching to emit_small_memset
|
||||
// FIXME use emit_small_memset
|
||||
fx.bcx.call_memset(fx.module.target_config(), dst_ptr, val, count);
|
||||
};
|
||||
ctlz | ctlz_nonzero, <T> (v arg) {
|
||||
|
@ -812,7 +833,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
|||
let pointee_size: u64 = fx.layout_of(T).size.bytes();
|
||||
let diff = fx.bcx.ins().isub(ptr, base);
|
||||
// FIXME this can be an exact division.
|
||||
let val = CValue::by_val(fx.bcx.ins().udiv_imm(diff, pointee_size as i64), isize_layout);
|
||||
let val = CValue::by_val(fx.bcx.ins().sdiv_imm(diff, pointee_size as i64), isize_layout);
|
||||
ret.write_cvalue(fx, val);
|
||||
};
|
||||
|
||||
|
@ -966,6 +987,28 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
|||
let ret_val = CValue::const_val(fx, ret.layout(), 0);
|
||||
ret.write_cvalue(fx, ret_val);
|
||||
};
|
||||
|
||||
fadd_fast | fsub_fast | fmul_fast | fdiv_fast | frem_fast, (c x, c y) {
|
||||
let res = crate::num::trans_float_binop(fx, match intrinsic {
|
||||
"fadd_fast" => BinOp::Add,
|
||||
"fsub_fast" => BinOp::Sub,
|
||||
"fmul_fast" => BinOp::Mul,
|
||||
"fdiv_fast" => BinOp::Div,
|
||||
"frem_fast" => BinOp::Rem,
|
||||
_ => unreachable!(),
|
||||
}, x, y);
|
||||
ret.write_cvalue(fx, res);
|
||||
};
|
||||
float_to_int_unchecked, (v f) {
|
||||
let res = crate::cast::clif_int_or_float_cast(
|
||||
fx,
|
||||
f,
|
||||
false,
|
||||
fx.clif_type(ret.layout().ty).unwrap(),
|
||||
type_sign(ret.layout().ty),
|
||||
);
|
||||
ret.write_cvalue(fx, CValue::by_val(res, ret.layout()));
|
||||
};
|
||||
}
|
||||
|
||||
if let Some((_, dest)) = destination {
|
||||
|
|
24
src/num.rs
24
src/num.rs
|
@ -168,16 +168,18 @@ pub(crate) fn trans_int_binop<'tcx>(
|
|||
BinOp::BitOr => b.bor(lhs, rhs),
|
||||
BinOp::Shl => {
|
||||
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
|
||||
let rhs = clif_intcast(fx, rhs, lhs_ty, false);
|
||||
fx.bcx.ins().ishl(lhs, rhs)
|
||||
let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
|
||||
let actual_shift = clif_intcast(fx, actual_shift, types::I8, false);
|
||||
fx.bcx.ins().ishl(lhs, actual_shift)
|
||||
}
|
||||
BinOp::Shr => {
|
||||
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
|
||||
let rhs = clif_intcast(fx, rhs, lhs_ty, false);
|
||||
let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
|
||||
let actual_shift = clif_intcast(fx, actual_shift, types::I8, false);
|
||||
if signed {
|
||||
fx.bcx.ins().sshr(lhs, rhs)
|
||||
fx.bcx.ins().sshr(lhs, actual_shift)
|
||||
} else {
|
||||
fx.bcx.ins().ushr(lhs, rhs)
|
||||
fx.bcx.ins().ushr(lhs, actual_shift)
|
||||
}
|
||||
}
|
||||
// Compare binops handles by `codegen_binop`.
|
||||
|
@ -283,7 +285,10 @@ pub(crate) fn trans_checked_int_binop<'tcx>(
|
|||
}
|
||||
}
|
||||
BinOp::Shl => {
|
||||
let val = fx.bcx.ins().ishl(lhs, rhs);
|
||||
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
|
||||
let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
|
||||
let actual_shift = clif_intcast(fx, actual_shift, types::I8, false);
|
||||
let val = fx.bcx.ins().ishl(lhs, actual_shift);
|
||||
let ty = fx.bcx.func.dfg.value_type(val);
|
||||
let max_shift = i64::from(ty.bits()) - 1;
|
||||
let has_overflow =
|
||||
|
@ -291,10 +296,13 @@ pub(crate) fn trans_checked_int_binop<'tcx>(
|
|||
(val, has_overflow)
|
||||
}
|
||||
BinOp::Shr => {
|
||||
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
|
||||
let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
|
||||
let actual_shift = clif_intcast(fx, actual_shift, types::I8, false);
|
||||
let val = if !signed {
|
||||
fx.bcx.ins().ushr(lhs, rhs)
|
||||
fx.bcx.ins().ushr(lhs, actual_shift)
|
||||
} else {
|
||||
fx.bcx.ins().sshr(lhs, rhs)
|
||||
fx.bcx.ins().sshr(lhs, actual_shift)
|
||||
};
|
||||
let ty = fx.bcx.func.dfg.value_type(val);
|
||||
let max_shift = i64::from(ty.bits()) - 1;
|
||||
|
|
Loading…
Reference in a new issue