Skip to content

Commit 6a5a086

Browse files
committed
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.
1 parent ee4cd86 commit 6a5a086

File tree

4 files changed

+78
-39
lines changed

4 files changed

+78
-39
lines changed

src/librustc/middle/lang_items.rs

+5
Original file line numberDiff line numberDiff line change
@@ -313,13 +313,17 @@ language_item_table! {
313313

314314
// A lang item for each of the 128-bit operators we can optionally lower.
315315
I128AddFnLangItem, "i128_add", i128_add_fn;
316+
U128AddFnLangItem, "u128_add", u128_add_fn;
316317
I128SubFnLangItem, "i128_sub", i128_sub_fn;
318+
U128SubFnLangItem, "u128_sub", u128_sub_fn;
317319
I128MulFnLangItem, "i128_mul", i128_mul_fn;
320+
U128MulFnLangItem, "u128_mul", u128_mul_fn;
318321
I128DivFnLangItem, "i128_div", i128_div_fn;
319322
U128DivFnLangItem, "u128_div", u128_div_fn;
320323
I128RemFnLangItem, "i128_rem", i128_rem_fn;
321324
U128RemFnLangItem, "u128_rem", u128_rem_fn;
322325
I128ShlFnLangItem, "i128_shl", i128_shl_fn;
326+
U128ShlFnLangItem, "u128_shl", u128_shl_fn;
323327
I128ShrFnLangItem, "i128_shr", i128_shr_fn;
324328
U128ShrFnLangItem, "u128_shr", u128_shr_fn;
325329
// And overflow versions for the operators that are checkable.
@@ -331,6 +335,7 @@ language_item_table! {
331335
I128MuloFnLangItem, "i128_mulo", i128_mulo_fn;
332336
U128MuloFnLangItem, "u128_mulo", u128_mulo_fn;
333337
I128ShloFnLangItem, "i128_shlo", i128_shlo_fn;
338+
U128ShloFnLangItem, "u128_shlo", u128_shlo_fn;
334339
I128ShroFnLangItem, "i128_shro", i128_shro_fn;
335340
U128ShroFnLangItem, "u128_shro", u128_shro_fn;
336341
}

src/librustc_mir/transform/lower_128bit.rs

+45-19
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ impl Lower128Bit {
4141
let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut();
4242
for block in basic_blocks.iter_mut() {
4343
for i in (0..block.statements.len()).rev() {
44-
let call_did =
45-
if let Some(call_did) = lower_to(&block.statements[i], local_decls, tcx) {
46-
call_did
44+
let lang_item =
45+
if let Some(lang_item) = lower_to(&block.statements[i], local_decls, tcx) {
46+
lang_item
4747
} else {
4848
continue;
4949
};
@@ -71,6 +71,9 @@ impl Lower128Bit {
7171
_ => bug!("Statement doesn't match pattern any more?"),
7272
};
7373

74+
let call_did = check_lang_item_type(
75+
lang_item, &lvalue, &lhs, &rhs, local_decls, tcx);
76+
7477
let bb = BasicBlock::new(cur_len + new_blocks.len());
7578
new_blocks.push(after_call);
7679

@@ -92,33 +95,51 @@ impl Lower128Bit {
9295
}
9396
}
9497

98+
fn check_lang_item_type<'a, 'tcx, D>(
99+
lang_item: LangItem,
100+
lvalue: &Lvalue<'tcx>,
101+
lhs: &Operand<'tcx>,
102+
rhs: &Operand<'tcx>,
103+
local_decls: &D,
104+
tcx: TyCtxt<'a, 'tcx, 'tcx>)
105+
-> DefId
106+
where D: HasLocalDecls<'tcx>
107+
{
108+
let did = tcx.require_lang_item(lang_item);
109+
let poly_sig = tcx.fn_sig(did);
110+
let sig = tcx.no_late_bound_regions(&poly_sig).unwrap();
111+
let lhs_ty = lhs.ty(local_decls, tcx);
112+
let rhs_ty = rhs.ty(local_decls, tcx);
113+
let lvalue_ty = lvalue.ty(local_decls, tcx).to_ty(tcx);
114+
let expected = [lhs_ty, rhs_ty, lvalue_ty];
115+
assert_eq!(sig.inputs_and_output[..], expected,
116+
"lang item {}", tcx.def_symbol_name(did));
117+
did
118+
}
119+
95120
fn lower_to<'a, 'tcx, D>(statement: &Statement<'tcx>, local_decls: &D, tcx: TyCtxt<'a, 'tcx, 'tcx>)
96-
-> Option<DefId>
121+
-> Option<LangItem>
97122
where D: HasLocalDecls<'tcx>
98123
{
99124
match statement.kind {
100125
StatementKind::Assign(_, Rvalue::BinaryOp(bin_op, ref lhs, _)) => {
101126
let ty = lhs.ty(local_decls, tcx);
102-
if let Some(is_signed) = sign_of_128bit(&ty) {
103-
if let Some(item) = item_for_op(bin_op, is_signed) {
104-
return Some(tcx.require_lang_item(item))
105-
}
127+
if let Some(is_signed) = sign_of_128bit(ty) {
128+
return item_for_op(bin_op, is_signed);
106129
}
107130
},
108131
StatementKind::Assign(_, Rvalue::CheckedBinaryOp(bin_op, ref lhs, _)) => {
109132
let ty = lhs.ty(local_decls, tcx);
110-
if let Some(is_signed) = sign_of_128bit(&ty) {
111-
if let Some(item) = item_for_checked_op(bin_op, is_signed) {
112-
return Some(tcx.require_lang_item(item))
113-
}
133+
if let Some(is_signed) = sign_of_128bit(ty) {
134+
return item_for_checked_op(bin_op, is_signed);
114135
}
115136
},
116137
_ => {},
117138
}
118139
None
119140
}
120141

121-
fn sign_of_128bit(ty: &Ty) -> Option<bool> {
142+
fn sign_of_128bit(ty: Ty) -> Option<bool> {
122143
match ty.sty {
123144
TypeVariants::TyInt(syntax::ast::IntTy::I128) => Some(true),
124145
TypeVariants::TyUint(syntax::ast::UintTy::U128) => Some(false),
@@ -128,14 +149,18 @@ fn sign_of_128bit(ty: &Ty) -> Option<bool> {
128149

129150
fn item_for_op(bin_op: BinOp, is_signed: bool) -> Option<LangItem> {
130151
let i = match (bin_op, is_signed) {
131-
(BinOp::Add, _) => LangItem::I128AddFnLangItem,
132-
(BinOp::Sub, _) => LangItem::I128SubFnLangItem,
133-
(BinOp::Mul, _) => LangItem::I128MulFnLangItem,
152+
(BinOp::Add, true) => LangItem::I128AddFnLangItem,
153+
(BinOp::Add, false) => LangItem::U128AddFnLangItem,
154+
(BinOp::Sub, true) => LangItem::I128SubFnLangItem,
155+
(BinOp::Sub, false) => LangItem::U128SubFnLangItem,
156+
(BinOp::Mul, true) => LangItem::I128MulFnLangItem,
157+
(BinOp::Mul, false) => LangItem::U128MulFnLangItem,
134158
(BinOp::Div, true) => LangItem::I128DivFnLangItem,
135159
(BinOp::Div, false) => LangItem::U128DivFnLangItem,
136160
(BinOp::Rem, true) => LangItem::I128RemFnLangItem,
137161
(BinOp::Rem, false) => LangItem::U128RemFnLangItem,
138-
(BinOp::Shl, _) => LangItem::I128ShlFnLangItem,
162+
(BinOp::Shl, true) => LangItem::I128ShlFnLangItem,
163+
(BinOp::Shl, false) => LangItem::U128ShlFnLangItem,
139164
(BinOp::Shr, true) => LangItem::I128ShrFnLangItem,
140165
(BinOp::Shr, false) => LangItem::U128ShrFnLangItem,
141166
_ => return None,
@@ -151,10 +176,11 @@ fn item_for_checked_op(bin_op: BinOp, is_signed: bool) -> Option<LangItem> {
151176
(BinOp::Sub, false) => LangItem::U128SuboFnLangItem,
152177
(BinOp::Mul, true) => LangItem::I128MuloFnLangItem,
153178
(BinOp::Mul, false) => LangItem::U128MuloFnLangItem,
154-
(BinOp::Shl, _) => LangItem::I128ShloFnLangItem,
179+
(BinOp::Shl, true) => LangItem::I128ShloFnLangItem,
180+
(BinOp::Shl, false) => LangItem::U128ShloFnLangItem,
155181
(BinOp::Shr, true) => LangItem::I128ShroFnLangItem,
156182
(BinOp::Shr, false) => LangItem::U128ShroFnLangItem,
157-
_ => return None,
183+
_ => bug!("That should be all the checked ones?"),
158184
};
159185
Some(i)
160186
}

src/test/mir-opt/lower_128bit_debug_test.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,32 @@
1616
#[lang="i128_div"]
1717
fn i128_div(_x: i128, _y: i128) -> i128 { 3 }
1818
#[lang="u128_div"]
19-
fn u128_div(_x: i128, _y: i128) -> i128 { 4 }
19+
fn u128_div(_x: u128, _y: u128) -> u128 { 4 }
2020
#[lang="i128_rem"]
2121
fn i128_rem(_x: i128, _y: i128) -> i128 { 5 }
2222
#[lang="u128_rem"]
23-
fn u128_rem(_x: i128, _y: i128) -> i128 { 6 }
23+
fn u128_rem(_x: u128, _y: u128) -> u128 { 6 }
2424

2525
#[lang="i128_addo"]
2626
fn i128_addo(_x: i128, _y: i128) -> (i128, bool) { (0, false) }
2727
#[lang="u128_addo"]
28-
fn u128_addo(_x: i128, _y: i128) -> (i128, bool) { (1, false) }
28+
fn u128_addo(_x: u128, _y: u128) -> (u128, bool) { (1, false) }
2929
#[lang="i128_subo"]
3030
fn i128_subo(_x: i128, _y: i128) -> (i128, bool) { (2, false) }
3131
#[lang="u128_subo"]
32-
fn u128_subo(_x: i128, _y: i128) -> (i128, bool) { (3, false) }
32+
fn u128_subo(_x: u128, _y: u128) -> (u128, bool) { (3, false) }
3333
#[lang="i128_mulo"]
3434
fn i128_mulo(_x: i128, _y: i128) -> (i128, bool) { (4, false) }
3535
#[lang="u128_mulo"]
36-
fn u128_mulo(_x: i128, _y: i128) -> (i128, bool) { (5, false) }
36+
fn u128_mulo(_x: u128, _y: u128) -> (u128, bool) { (5, false) }
3737
#[lang="i128_shlo"]
38-
fn i128_shlo(_x: i128, _y: u32) -> (i128, bool) { (6, false) }
38+
fn i128_shlo(_x: i128, _y: i32) -> (i128, bool) { (6, false) }
39+
#[lang="u128_shlo"]
40+
fn u128_shlo(_x: u128, _y: i32) -> (u128, bool) { (6, false) }
3941
#[lang="i128_shro"]
40-
fn i128_shro(_x: i128, _y: u32) -> (i128, bool) { (7, false) }
42+
fn i128_shro(_x: i128, _y: i32) -> (i128, bool) { (7, false) }
4143
#[lang="u128_shro"]
42-
fn u128_shro(_x: i128, _y: u32) -> (i128, bool) { (8, false) }
43-
44+
fn u128_shro(_x: u128, _y: i32) -> (u128, bool) { (8, false) }
4445

4546
fn test_signed(mut x: i128) -> i128 {
4647
x += 1;
@@ -132,7 +133,7 @@ fn main() {
132133
// ...
133134
// assert(!(_7.1: bool), "attempt to shift left with overflow") -> bb6;
134135
// ...
135-
// _7 = const i128_shlo(_1, const 6i32) -> bb12;
136+
// _7 = const u128_shlo(_1, const 6i32) -> bb12;
136137
// ...
137138
// assert(!(_8.1: bool), "attempt to shift right with overflow") -> bb7;
138139
// END rustc.test_unsigned.Lower128Bit.after.mir

src/test/mir-opt/lower_128bit_test.rs

+17-10
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,32 @@
1515

1616
#[lang="i128_add"]
1717
fn i128_add(_x: i128, _y: i128) -> i128 { 0 }
18+
#[lang="u128_add"]
19+
fn u128_add(_x: u128, _y: u128) -> u128 { 0 }
1820
#[lang="i128_sub"]
1921
fn i128_sub(_x: i128, _y: i128) -> i128 { 1 }
22+
#[lang="u128_sub"]
23+
fn u128_sub(_x: u128, _y: u128) -> u128 { 1 }
2024
#[lang="i128_mul"]
2125
fn i128_mul(_x: i128, _y: i128) -> i128 { 2 }
26+
#[lang="u128_mul"]
27+
fn u128_mul(_x: u128, _y: u128) -> u128 { 2 }
2228
#[lang="i128_div"]
2329
fn i128_div(_x: i128, _y: i128) -> i128 { 3 }
2430
#[lang="u128_div"]
25-
fn u128_div(_x: i128, _y: i128) -> i128 { 4 }
31+
fn u128_div(_x: u128, _y: u128) -> u128 { 4 }
2632
#[lang="i128_rem"]
2733
fn i128_rem(_x: i128, _y: i128) -> i128 { 5 }
2834
#[lang="u128_rem"]
29-
fn u128_rem(_x: i128, _y: i128) -> i128 { 6 }
35+
fn u128_rem(_x: u128, _y: u128) -> u128 { 6 }
3036
#[lang="i128_shl"]
31-
fn i128_shl(_x: i128, _y: u32) -> i128 { 7 }
37+
fn i128_shl(_x: i128, _y: i32) -> i128 { 7 }
38+
#[lang="u128_shl"]
39+
fn u128_shl(_x: u128, _y: i32) -> u128 { 7 }
3240
#[lang="i128_shr"]
33-
fn i128_shr(_x: i128, _y: u32) -> i128 { 8 }
41+
fn i128_shr(_x: i128, _y: i32) -> i128 { 8 }
3442
#[lang="u128_shr"]
35-
fn u128_shr(_x: i128, _y: u32) -> i128 { 9 }
36-
43+
fn u128_shr(_x: u128, _y: i32) -> u128 { 9 }
3744

3845
fn test_signed(mut x: i128) -> i128 {
3946
x += 1;
@@ -81,17 +88,17 @@ fn main() {
8188
// END rustc.test_signed.Lower128Bit.after.mir
8289

8390
// START rustc.test_unsigned.Lower128Bit.after.mir
84-
// _1 = const i128_add(_1, const 1u128) -> bb5;
91+
// _1 = const u128_add(_1, const 1u128) -> bb5;
8592
// ...
8693
// _1 = const u128_div(_1, const 4u128) -> bb6;
8794
// ...
8895
// _1 = const u128_rem(_1, const 5u128) -> bb9;
8996
// ...
90-
// _1 = const i128_mul(_1, const 3u128) -> bb3;
97+
// _1 = const u128_mul(_1, const 3u128) -> bb3;
9198
// ...
92-
// _1 = const i128_sub(_1, const 2u128) -> bb4;
99+
// _1 = const u128_sub(_1, const 2u128) -> bb4;
93100
// ...
94101
// _1 = const u128_shr(_1, const 7i32) -> bb7;
95102
// ...
96-
// _1 = const i128_shl(_1, const 6i32) -> bb8;
103+
// _1 = const u128_shl(_1, const 6i32) -> bb8;
97104
// END rustc.test_unsigned.Lower128Bit.after.mir

0 commit comments

Comments
 (0)