Add type checking for the lang item
As part of doing so, add more lang items instead of passing u128 to the i128 ones where it doesn't matter in twos-complement.
This commit is contained in:
parent
ee4cd865df
commit
6a5a086fd6
@ -313,13 +313,17 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
|
||||
|
||||
// A lang item for each of the 128-bit operators we can optionally lower.
|
||||
I128AddFnLangItem, "i128_add", i128_add_fn;
|
||||
U128AddFnLangItem, "u128_add", u128_add_fn;
|
||||
I128SubFnLangItem, "i128_sub", i128_sub_fn;
|
||||
U128SubFnLangItem, "u128_sub", u128_sub_fn;
|
||||
I128MulFnLangItem, "i128_mul", i128_mul_fn;
|
||||
U128MulFnLangItem, "u128_mul", u128_mul_fn;
|
||||
I128DivFnLangItem, "i128_div", i128_div_fn;
|
||||
U128DivFnLangItem, "u128_div", u128_div_fn;
|
||||
I128RemFnLangItem, "i128_rem", i128_rem_fn;
|
||||
U128RemFnLangItem, "u128_rem", u128_rem_fn;
|
||||
I128ShlFnLangItem, "i128_shl", i128_shl_fn;
|
||||
U128ShlFnLangItem, "u128_shl", u128_shl_fn;
|
||||
I128ShrFnLangItem, "i128_shr", i128_shr_fn;
|
||||
U128ShrFnLangItem, "u128_shr", u128_shr_fn;
|
||||
// And overflow versions for the operators that are checkable.
|
||||
@ -331,6 +335,7 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
|
||||
I128MuloFnLangItem, "i128_mulo", i128_mulo_fn;
|
||||
U128MuloFnLangItem, "u128_mulo", u128_mulo_fn;
|
||||
I128ShloFnLangItem, "i128_shlo", i128_shlo_fn;
|
||||
U128ShloFnLangItem, "u128_shlo", u128_shlo_fn;
|
||||
I128ShroFnLangItem, "i128_shro", i128_shro_fn;
|
||||
U128ShroFnLangItem, "u128_shro", u128_shro_fn;
|
||||
}
|
||||
|
@ -41,9 +41,9 @@ fn lower_128bit_ops<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<
|
||||
let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut();
|
||||
for block in basic_blocks.iter_mut() {
|
||||
for i in (0..block.statements.len()).rev() {
|
||||
let call_did =
|
||||
if let Some(call_did) = lower_to(&block.statements[i], local_decls, tcx) {
|
||||
call_did
|
||||
let lang_item =
|
||||
if let Some(lang_item) = lower_to(&block.statements[i], local_decls, tcx) {
|
||||
lang_item
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
@ -71,6 +71,9 @@ fn lower_128bit_ops<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<
|
||||
_ => bug!("Statement doesn't match pattern any more?"),
|
||||
};
|
||||
|
||||
let call_did = check_lang_item_type(
|
||||
lang_item, &lvalue, &lhs, &rhs, local_decls, tcx);
|
||||
|
||||
let bb = BasicBlock::new(cur_len + new_blocks.len());
|
||||
new_blocks.push(after_call);
|
||||
|
||||
@ -92,25 +95,43 @@ fn lower_128bit_ops<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<
|
||||
}
|
||||
}
|
||||
|
||||
fn check_lang_item_type<'a, 'tcx, D>(
|
||||
lang_item: LangItem,
|
||||
lvalue: &Lvalue<'tcx>,
|
||||
lhs: &Operand<'tcx>,
|
||||
rhs: &Operand<'tcx>,
|
||||
local_decls: &D,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||
-> DefId
|
||||
where D: HasLocalDecls<'tcx>
|
||||
{
|
||||
let did = tcx.require_lang_item(lang_item);
|
||||
let poly_sig = tcx.fn_sig(did);
|
||||
let sig = tcx.no_late_bound_regions(&poly_sig).unwrap();
|
||||
let lhs_ty = lhs.ty(local_decls, tcx);
|
||||
let rhs_ty = rhs.ty(local_decls, tcx);
|
||||
let lvalue_ty = lvalue.ty(local_decls, tcx).to_ty(tcx);
|
||||
let expected = [lhs_ty, rhs_ty, lvalue_ty];
|
||||
assert_eq!(sig.inputs_and_output[..], expected,
|
||||
"lang item {}", tcx.def_symbol_name(did));
|
||||
did
|
||||
}
|
||||
|
||||
fn lower_to<'a, 'tcx, D>(statement: &Statement<'tcx>, local_decls: &D, tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||
-> Option<DefId>
|
||||
-> Option<LangItem>
|
||||
where D: HasLocalDecls<'tcx>
|
||||
{
|
||||
match statement.kind {
|
||||
StatementKind::Assign(_, Rvalue::BinaryOp(bin_op, ref lhs, _)) => {
|
||||
let ty = lhs.ty(local_decls, tcx);
|
||||
if let Some(is_signed) = sign_of_128bit(&ty) {
|
||||
if let Some(item) = item_for_op(bin_op, is_signed) {
|
||||
return Some(tcx.require_lang_item(item))
|
||||
}
|
||||
if let Some(is_signed) = sign_of_128bit(ty) {
|
||||
return item_for_op(bin_op, is_signed);
|
||||
}
|
||||
},
|
||||
StatementKind::Assign(_, Rvalue::CheckedBinaryOp(bin_op, ref lhs, _)) => {
|
||||
let ty = lhs.ty(local_decls, tcx);
|
||||
if let Some(is_signed) = sign_of_128bit(&ty) {
|
||||
if let Some(item) = item_for_checked_op(bin_op, is_signed) {
|
||||
return Some(tcx.require_lang_item(item))
|
||||
}
|
||||
if let Some(is_signed) = sign_of_128bit(ty) {
|
||||
return item_for_checked_op(bin_op, is_signed);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
@ -118,7 +139,7 @@ fn lower_to<'a, 'tcx, D>(statement: &Statement<'tcx>, local_decls: &D, tcx: TyCt
|
||||
None
|
||||
}
|
||||
|
||||
fn sign_of_128bit(ty: &Ty) -> Option<bool> {
|
||||
fn sign_of_128bit(ty: Ty) -> Option<bool> {
|
||||
match ty.sty {
|
||||
TypeVariants::TyInt(syntax::ast::IntTy::I128) => Some(true),
|
||||
TypeVariants::TyUint(syntax::ast::UintTy::U128) => Some(false),
|
||||
@ -128,14 +149,18 @@ fn sign_of_128bit(ty: &Ty) -> Option<bool> {
|
||||
|
||||
fn item_for_op(bin_op: BinOp, is_signed: bool) -> Option<LangItem> {
|
||||
let i = match (bin_op, is_signed) {
|
||||
(BinOp::Add, _) => LangItem::I128AddFnLangItem,
|
||||
(BinOp::Sub, _) => LangItem::I128SubFnLangItem,
|
||||
(BinOp::Mul, _) => LangItem::I128MulFnLangItem,
|
||||
(BinOp::Add, true) => LangItem::I128AddFnLangItem,
|
||||
(BinOp::Add, false) => LangItem::U128AddFnLangItem,
|
||||
(BinOp::Sub, true) => LangItem::I128SubFnLangItem,
|
||||
(BinOp::Sub, false) => LangItem::U128SubFnLangItem,
|
||||
(BinOp::Mul, true) => LangItem::I128MulFnLangItem,
|
||||
(BinOp::Mul, false) => LangItem::U128MulFnLangItem,
|
||||
(BinOp::Div, true) => LangItem::I128DivFnLangItem,
|
||||
(BinOp::Div, false) => LangItem::U128DivFnLangItem,
|
||||
(BinOp::Rem, true) => LangItem::I128RemFnLangItem,
|
||||
(BinOp::Rem, false) => LangItem::U128RemFnLangItem,
|
||||
(BinOp::Shl, _) => LangItem::I128ShlFnLangItem,
|
||||
(BinOp::Shl, true) => LangItem::I128ShlFnLangItem,
|
||||
(BinOp::Shl, false) => LangItem::U128ShlFnLangItem,
|
||||
(BinOp::Shr, true) => LangItem::I128ShrFnLangItem,
|
||||
(BinOp::Shr, false) => LangItem::U128ShrFnLangItem,
|
||||
_ => return None,
|
||||
@ -151,10 +176,11 @@ fn item_for_checked_op(bin_op: BinOp, is_signed: bool) -> Option<LangItem> {
|
||||
(BinOp::Sub, false) => LangItem::U128SuboFnLangItem,
|
||||
(BinOp::Mul, true) => LangItem::I128MuloFnLangItem,
|
||||
(BinOp::Mul, false) => LangItem::U128MuloFnLangItem,
|
||||
(BinOp::Shl, _) => LangItem::I128ShloFnLangItem,
|
||||
(BinOp::Shl, true) => LangItem::I128ShloFnLangItem,
|
||||
(BinOp::Shl, false) => LangItem::U128ShloFnLangItem,
|
||||
(BinOp::Shr, true) => LangItem::I128ShroFnLangItem,
|
||||
(BinOp::Shr, false) => LangItem::U128ShroFnLangItem,
|
||||
_ => return None,
|
||||
_ => bug!("That should be all the checked ones?"),
|
||||
};
|
||||
Some(i)
|
||||
}
|
@ -16,31 +16,32 @@
|
||||
#[lang="i128_div"]
|
||||
fn i128_div(_x: i128, _y: i128) -> i128 { 3 }
|
||||
#[lang="u128_div"]
|
||||
fn u128_div(_x: i128, _y: i128) -> i128 { 4 }
|
||||
fn u128_div(_x: u128, _y: u128) -> u128 { 4 }
|
||||
#[lang="i128_rem"]
|
||||
fn i128_rem(_x: i128, _y: i128) -> i128 { 5 }
|
||||
#[lang="u128_rem"]
|
||||
fn u128_rem(_x: i128, _y: i128) -> i128 { 6 }
|
||||
fn u128_rem(_x: u128, _y: u128) -> u128 { 6 }
|
||||
|
||||
#[lang="i128_addo"]
|
||||
fn i128_addo(_x: i128, _y: i128) -> (i128, bool) { (0, false) }
|
||||
#[lang="u128_addo"]
|
||||
fn u128_addo(_x: i128, _y: i128) -> (i128, bool) { (1, false) }
|
||||
fn u128_addo(_x: u128, _y: u128) -> (u128, bool) { (1, false) }
|
||||
#[lang="i128_subo"]
|
||||
fn i128_subo(_x: i128, _y: i128) -> (i128, bool) { (2, false) }
|
||||
#[lang="u128_subo"]
|
||||
fn u128_subo(_x: i128, _y: i128) -> (i128, bool) { (3, false) }
|
||||
fn u128_subo(_x: u128, _y: u128) -> (u128, bool) { (3, false) }
|
||||
#[lang="i128_mulo"]
|
||||
fn i128_mulo(_x: i128, _y: i128) -> (i128, bool) { (4, false) }
|
||||
#[lang="u128_mulo"]
|
||||
fn u128_mulo(_x: i128, _y: i128) -> (i128, bool) { (5, false) }
|
||||
fn u128_mulo(_x: u128, _y: u128) -> (u128, bool) { (5, false) }
|
||||
#[lang="i128_shlo"]
|
||||
fn i128_shlo(_x: i128, _y: u32) -> (i128, bool) { (6, false) }
|
||||
fn i128_shlo(_x: i128, _y: i32) -> (i128, bool) { (6, false) }
|
||||
#[lang="u128_shlo"]
|
||||
fn u128_shlo(_x: u128, _y: i32) -> (u128, bool) { (6, false) }
|
||||
#[lang="i128_shro"]
|
||||
fn i128_shro(_x: i128, _y: u32) -> (i128, bool) { (7, false) }
|
||||
fn i128_shro(_x: i128, _y: i32) -> (i128, bool) { (7, false) }
|
||||
#[lang="u128_shro"]
|
||||
fn u128_shro(_x: i128, _y: u32) -> (i128, bool) { (8, false) }
|
||||
|
||||
fn u128_shro(_x: u128, _y: i32) -> (u128, bool) { (8, false) }
|
||||
|
||||
fn test_signed(mut x: i128) -> i128 {
|
||||
x += 1;
|
||||
@ -132,7 +133,7 @@ fn main() {
|
||||
// ...
|
||||
// assert(!(_7.1: bool), "attempt to shift left with overflow") -> bb6;
|
||||
// ...
|
||||
// _7 = const i128_shlo(_1, const 6i32) -> bb12;
|
||||
// _7 = const u128_shlo(_1, const 6i32) -> bb12;
|
||||
// ...
|
||||
// assert(!(_8.1: bool), "attempt to shift right with overflow") -> bb7;
|
||||
// END rustc.test_unsigned.Lower128Bit.after.mir
|
||||
|
@ -15,25 +15,32 @@
|
||||
|
||||
#[lang="i128_add"]
|
||||
fn i128_add(_x: i128, _y: i128) -> i128 { 0 }
|
||||
#[lang="u128_add"]
|
||||
fn u128_add(_x: u128, _y: u128) -> u128 { 0 }
|
||||
#[lang="i128_sub"]
|
||||
fn i128_sub(_x: i128, _y: i128) -> i128 { 1 }
|
||||
#[lang="u128_sub"]
|
||||
fn u128_sub(_x: u128, _y: u128) -> u128 { 1 }
|
||||
#[lang="i128_mul"]
|
||||
fn i128_mul(_x: i128, _y: i128) -> i128 { 2 }
|
||||
#[lang="u128_mul"]
|
||||
fn u128_mul(_x: u128, _y: u128) -> u128 { 2 }
|
||||
#[lang="i128_div"]
|
||||
fn i128_div(_x: i128, _y: i128) -> i128 { 3 }
|
||||
#[lang="u128_div"]
|
||||
fn u128_div(_x: i128, _y: i128) -> i128 { 4 }
|
||||
fn u128_div(_x: u128, _y: u128) -> u128 { 4 }
|
||||
#[lang="i128_rem"]
|
||||
fn i128_rem(_x: i128, _y: i128) -> i128 { 5 }
|
||||
#[lang="u128_rem"]
|
||||
fn u128_rem(_x: i128, _y: i128) -> i128 { 6 }
|
||||
fn u128_rem(_x: u128, _y: u128) -> u128 { 6 }
|
||||
#[lang="i128_shl"]
|
||||
fn i128_shl(_x: i128, _y: u32) -> i128 { 7 }
|
||||
fn i128_shl(_x: i128, _y: i32) -> i128 { 7 }
|
||||
#[lang="u128_shl"]
|
||||
fn u128_shl(_x: u128, _y: i32) -> u128 { 7 }
|
||||
#[lang="i128_shr"]
|
||||
fn i128_shr(_x: i128, _y: u32) -> i128 { 8 }
|
||||
fn i128_shr(_x: i128, _y: i32) -> i128 { 8 }
|
||||
#[lang="u128_shr"]
|
||||
fn u128_shr(_x: i128, _y: u32) -> i128 { 9 }
|
||||
|
||||
fn u128_shr(_x: u128, _y: i32) -> u128 { 9 }
|
||||
|
||||
fn test_signed(mut x: i128) -> i128 {
|
||||
x += 1;
|
||||
@ -81,17 +88,17 @@ fn main() {
|
||||
// END rustc.test_signed.Lower128Bit.after.mir
|
||||
|
||||
// START rustc.test_unsigned.Lower128Bit.after.mir
|
||||
// _1 = const i128_add(_1, const 1u128) -> bb5;
|
||||
// _1 = const u128_add(_1, const 1u128) -> bb5;
|
||||
// ...
|
||||
// _1 = const u128_div(_1, const 4u128) -> bb6;
|
||||
// ...
|
||||
// _1 = const u128_rem(_1, const 5u128) -> bb9;
|
||||
// ...
|
||||
// _1 = const i128_mul(_1, const 3u128) -> bb3;
|
||||
// _1 = const u128_mul(_1, const 3u128) -> bb3;
|
||||
// ...
|
||||
// _1 = const i128_sub(_1, const 2u128) -> bb4;
|
||||
// _1 = const u128_sub(_1, const 2u128) -> bb4;
|
||||
// ...
|
||||
// _1 = const u128_shr(_1, const 7i32) -> bb7;
|
||||
// ...
|
||||
// _1 = const i128_shl(_1, const 6i32) -> bb8;
|
||||
// _1 = const u128_shl(_1, const 6i32) -> bb8;
|
||||
// END rustc.test_unsigned.Lower128Bit.after.mir
|
||||
|
Loading…
Reference in New Issue
Block a user