More 128bit support

* UnOp::Neg
* ctpop
* bitreverse

Also replaces `if let Some(64u128) = ...` with `if ... = Some(u64u128)`
to be able to compile cg_clif using cg_clif, as cranelift_frontend::Switch
doesn't support i128 yet.
This commit is contained in:
bjorn3 2019-10-06 15:51:43 +02:00
parent b5d29a8c58
commit 6129921529
3 changed files with 31 additions and 20 deletions

View File

@ -313,33 +313,26 @@ fn trans_stmt<'tcx>(
ty::Bool => {
let val = fx.bcx.ins().uextend(types::I32, val); // WORKAROUND for CraneStation/cranelift#466
let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0);
fx.bcx.ins().bint(types::I8, res)
CValue::by_val(fx.bcx.ins().bint(types::I8, res), layout)
}
ty::Uint(_) | ty::Int(_) => {
CValue::by_val(fx.bcx.ins().bnot(val), layout)
}
ty::Uint(_) | ty::Int(_) => fx.bcx.ins().bnot(val),
_ => unimplemented!("un op Not for {:?}", layout.ty),
}
}
UnOp::Neg => match layout.ty.kind {
ty::Int(_) => {
let clif_ty = fx.clif_type(layout.ty).unwrap();
if clif_ty == types::I128 {
// FIXME implement it
crate::trap::trap_unreachable_ret_value(
fx,
layout,
"i128 neg is not yet supported",
)
.load_scalar(fx)
} else {
let zero = fx.bcx.ins().iconst(clif_ty, 0);
fx.bcx.ins().isub(zero, val)
let zero = CValue::const_val(fx, layout.ty, 0);
crate::num::trans_int_binop(fx, BinOp::Sub, zero, operand)
}
ty::Float(_) => {
CValue::by_val(fx.bcx.ins().fneg(val), layout)
}
ty::Float(_) => fx.bcx.ins().fneg(val),
_ => unimplemented!("un op Neg for {:?}", layout.ty),
},
};
lval.write_cvalue(fx, CValue::by_val(res, layout));
lval.write_cvalue(fx, res);
}
Rvalue::Cast(CastKind::Pointer(PointerCast::ReifyFnPointer), operand, ty) => {
let layout = fx.layout_of(ty);

View File

@ -98,7 +98,7 @@ pub fn maybe_codegen<'tcx>(
// Optimize `val >> 64`, because compiler_builtins uses it to deconstruct an 128bit
// integer into its lsb and msb.
// https://github.com/rust-lang-nursery/compiler-builtins/blob/79a6a1603d5672cbb9187ff41ff4d9b5048ac1cb/src/int/mod.rs#L217
if let Some(64) = resolve_value_imm(fx.bcx.func, rhs_val) {
if resolve_value_imm(fx.bcx.func, rhs_val) == Some(64) {
let (lhs_lsb, lhs_msb) = fx.bcx.ins().isplit(lhs_val);
let all_zeros = fx.bcx.ins().iconst(types::I64, 0);
let val = match (bin_op, is_signed) {

View File

@ -700,11 +700,29 @@ pub fn codegen_intrinsic_call<'tcx>(
ret.write_cvalue(fx, res);
};
ctpop, <T> (v arg) {
let res = CValue::by_val(fx.bcx.ins().popcnt(arg), fx.layout_of(T));
let res = if T == fx.tcx.types.u128 || T == fx.tcx.types.i128 {
let (lo, hi) = fx.bcx.ins().isplit(arg);
let lo_popcnt = fx.bcx.ins().popcnt(lo);
let hi_popcnt = fx.bcx.ins().popcnt(hi);
let popcnt = fx.bcx.ins().iadd(lo_popcnt, hi_popcnt);
crate::cast::clif_intcast(fx, popcnt, types::I128, false)
} else {
fx.bcx.ins().popcnt(arg)
};
let res = CValue::by_val(res, fx.layout_of(T));
ret.write_cvalue(fx, res);
};
bitreverse, <T> (v arg) {
let res = CValue::by_val(fx.bcx.ins().bitrev(arg), fx.layout_of(T));
let res = if T == fx.tcx.types.u128 || T == fx.tcx.types.i128 {
let (lo, hi) = fx.bcx.ins().isplit(arg);
let lo_bitrev = fx.bcx.ins().bitrev(lo);
let hi_bitrev = fx.bcx.ins().bitrev(hi);
let bitrev = fx.bcx.ins().iconcat(hi_bitrev, lo_bitrev);
crate::cast::clif_intcast(fx, bitrev, types::I128, false)
} else {
fx.bcx.ins().bitrev(arg)
};
let res = CValue::by_val(res, fx.layout_of(T));
ret.write_cvalue(fx, res);
};
bswap, <T> (v arg) {