diff --git a/example/std_example.rs b/example/std_example.rs index a67ca2f79c7..9e9a7a67e05 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -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); } diff --git a/src/abi.rs b/src/abi.rs index 1c9f84b37e4..b884d80b394 100644 --- a/src/abi.rs +++ b/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, - output_ty: Option, + output_tys: Vec, args: &[Value], - ) -> Option { + ) -> &[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( (...) -> ) 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!(), } } diff --git a/src/codegen_i128.rs b/src/codegen_i128.rs index 81388573c9e..b5e2bb6b3c9 100644 --- a/src/codegen_i128.rs +++ b/src/codegen_i128.rs @@ -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 };