Implement 128bit multiply with overflow
This commit is contained in:
parent
88ad25f45e
commit
65e337cdf3
@ -22,4 +22,9 @@ fn main() {
|
||||
checked_div_i128(0i128, 2i128);
|
||||
checked_div_u128(0u128, 2u128);
|
||||
assert_eq!(1u128 + 2, 3);
|
||||
|
||||
println!("{}", 0b100010000000000000000000000000000u128 >> 10);
|
||||
println!("{}", 0xFEDCBA987654321123456789ABCDEFu128 >> 64);
|
||||
println!("{} >> 64 == {}", 0xFEDCBA987654321123456789ABCDEFu128 as i128, 0xFEDCBA987654321123456789ABCDEFu128 as i128 >> 64);
|
||||
println!("{}", 353985398u128 * 932490u128);
|
||||
}
|
||||
|
36
src/abi.rs
36
src/abi.rs
@ -252,14 +252,12 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
|
||||
&mut self,
|
||||
name: &str,
|
||||
input_tys: Vec<types::Type>,
|
||||
output_ty: Option<types::Type>,
|
||||
output_tys: Vec<types::Type>,
|
||||
args: &[Value],
|
||||
) -> Option<Value> {
|
||||
) -> &[Value] {
|
||||
let sig = Signature {
|
||||
params: input_tys.iter().cloned().map(AbiParam::new).collect(),
|
||||
returns: output_ty
|
||||
.map(|output_ty| vec![AbiParam::new(output_ty)])
|
||||
.unwrap_or(Vec::new()),
|
||||
returns: output_tys.iter().cloned().map(AbiParam::new).collect(),
|
||||
call_conv: CallConv::SystemV,
|
||||
};
|
||||
let func_id = self
|
||||
@ -271,12 +269,9 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
|
||||
.declare_func_in_func(func_id, &mut self.bcx.func);
|
||||
let call_inst = self.bcx.ins().call(func_ref, args);
|
||||
self.add_comment(call_inst, format!("easy_call {}", name));
|
||||
if output_ty.is_none() {
|
||||
return None;
|
||||
}
|
||||
let results = self.bcx.inst_results(call_inst);
|
||||
assert_eq!(results.len(), 1);
|
||||
Some(results[0])
|
||||
assert!(results.len() <= 2, "{}", results.len());
|
||||
results
|
||||
}
|
||||
|
||||
pub fn easy_call(
|
||||
@ -295,23 +290,22 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
|
||||
})
|
||||
.unzip();
|
||||
let return_layout = self.layout_of(return_ty);
|
||||
let return_ty = if let ty::Tuple(tup) = return_ty.sty {
|
||||
if !tup.is_empty() {
|
||||
bug!("easy_call( (...) -> <non empty tuple> ) is not allowed");
|
||||
}
|
||||
None
|
||||
let return_tys = if let ty::Tuple(tup) = return_ty.sty {
|
||||
tup.types().map(|ty| self.clif_type(ty).unwrap()).collect()
|
||||
} else {
|
||||
Some(self.clif_type(return_ty).unwrap())
|
||||
vec![self.clif_type(return_ty).unwrap()]
|
||||
};
|
||||
if let Some(val) = self.lib_call(name, input_tys, return_ty, &args) {
|
||||
CValue::by_val(val, return_layout)
|
||||
} else {
|
||||
CValue::by_ref(
|
||||
let ret_vals = self.lib_call(name, input_tys, return_tys, &args);
|
||||
match *ret_vals {
|
||||
[] => CValue::by_ref(
|
||||
self.bcx
|
||||
.ins()
|
||||
.iconst(self.pointer_type, self.pointer_type.bytes() as i64),
|
||||
return_layout,
|
||||
)
|
||||
),
|
||||
[val] => CValue::by_val(val, return_layout),
|
||||
[val, extra] => CValue::by_val_pair(val, extra, return_layout),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,19 +30,9 @@ pub fn maybe_codegen<'a, 'tcx>(
|
||||
BinOp::Mul => {
|
||||
let res = if checked {
|
||||
if is_signed {
|
||||
let oflow_place = CPlace::new_stack_slot(fx, fx.tcx.types.i32);
|
||||
let oflow_addr = oflow_place.to_addr(fx);
|
||||
let oflow_addr = CValue::by_val(oflow_addr, fx.layout_of(fx.tcx.mk_mut_ptr(fx.tcx.types.i32)));
|
||||
let val = fx.easy_call("__muloti4", &[lhs, rhs, oflow_addr], fx.tcx.types.i128);
|
||||
let val = val.load_scalar(fx);
|
||||
let oflow = oflow_place.to_cvalue(fx).load_scalar(fx);
|
||||
let oflow = fx.bcx.ins().icmp_imm(IntCC::NotEqual, oflow, 0);
|
||||
let oflow = fx.bcx.ins().bint(types::I8, oflow);
|
||||
CValue::by_val_pair(val, oflow, fx.layout_of(out_ty))
|
||||
fx.easy_call("__rust_i128_mulo", &[lhs, rhs], out_ty)
|
||||
} else {
|
||||
// FIXME implement it
|
||||
let out_layout = fx.layout_of(out_ty);
|
||||
return Some(crate::trap::trap_unreachable_ret_value(fx, out_layout, format!("unimplemented 128bit checked binop unsigned mul")));
|
||||
fx.easy_call("__rust_u128_mulo", &[lhs, rhs], out_ty)
|
||||
}
|
||||
} else {
|
||||
let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
|
||||
@ -51,32 +41,20 @@ pub fn maybe_codegen<'a, 'tcx>(
|
||||
return Some(res);
|
||||
}
|
||||
BinOp::Div => {
|
||||
let res = if checked {
|
||||
// FIXME implement it
|
||||
let out_layout = fx.layout_of(out_ty);
|
||||
return Some(crate::trap::trap_unreachable_ret_value(fx, out_layout, format!("unimplemented 128bit checked binop div")));
|
||||
assert!(!checked);
|
||||
if is_signed {
|
||||
Some(fx.easy_call("__divti3", &[lhs, rhs], fx.tcx.types.i128))
|
||||
} else {
|
||||
if is_signed {
|
||||
fx.easy_call("__divti3", &[lhs, rhs], fx.tcx.types.i128)
|
||||
} else {
|
||||
fx.easy_call("__udivti3", &[lhs, rhs], fx.tcx.types.u128)
|
||||
}
|
||||
};
|
||||
return Some(res);
|
||||
Some(fx.easy_call("__udivti3", &[lhs, rhs], fx.tcx.types.u128))
|
||||
}
|
||||
}
|
||||
BinOp::Rem => {
|
||||
let res = if checked {
|
||||
// FIXME implement it
|
||||
let out_layout = fx.layout_of(out_ty);
|
||||
return Some(crate::trap::trap_unreachable_ret_value(fx, out_layout, format!("unimplemented 128bit checked binop rem")));
|
||||
assert!(!checked);
|
||||
if is_signed {
|
||||
Some(fx.easy_call("__modti3", &[lhs, rhs], fx.tcx.types.i128))
|
||||
} else {
|
||||
if is_signed {
|
||||
fx.easy_call("__modti3", &[lhs, rhs], fx.tcx.types.i128)
|
||||
} else {
|
||||
fx.easy_call("__umodti3", &[lhs, rhs], fx.tcx.types.u128)
|
||||
}
|
||||
};
|
||||
return Some(res);
|
||||
Some(fx.easy_call("__umodti3", &[lhs, rhs], fx.tcx.types.u128))
|
||||
}
|
||||
}
|
||||
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => {
|
||||
assert!(!checked);
|
||||
@ -140,8 +118,9 @@ pub fn maybe_codegen<'a, 'tcx>(
|
||||
Some(CValue::by_val(val, fx.layout_of(fx.tcx.types.i128)))
|
||||
}
|
||||
(BinOp::Shl, _) => {
|
||||
let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
|
||||
let val = fx.bcx.ins().iconcat(all_zeros, lhs_lsb);
|
||||
Some(CValue::by_val(val, fx.layout_of(out_ty)))
|
||||
Some(CValue::by_val(val, fx.layout_of(val_ty)))
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user