Merge pull request #1056 from bjorn3/misc_fixes

Misc fixes
This commit is contained in:
bjorn3 2020-06-30 19:20:44 +02:00 committed by GitHub
commit 6e2ac83a0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 106 additions and 23 deletions

View file

@ -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);

View file

@ -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) {

View file

@ -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 {

View file

@ -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;