Skip to content

Commit bba11f6

Browse files
authored
Merge pull request #646 from bjorn3/wip_checked_binops2
Implement checked add and sub
2 parents 92f2b62 + bf3ec3b commit bba11f6

File tree

3 files changed

+119
-11
lines changed

3 files changed

+119
-11
lines changed

example/mini_core.rs

+48
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ impl Add for u8 {
128128
}
129129
}
130130

131+
impl Add for i8 {
132+
type Output = Self;
133+
134+
fn add(self, rhs: Self) -> Self {
135+
self + rhs
136+
}
137+
}
138+
131139
impl Add for usize {
132140
type Output = Self;
133141

@@ -151,6 +159,30 @@ impl Sub for usize {
151159
}
152160
}
153161

162+
impl Sub for u8 {
163+
type Output = Self;
164+
165+
fn sub(self, rhs: Self) -> Self {
166+
self - rhs
167+
}
168+
}
169+
170+
impl Sub for i8 {
171+
type Output = Self;
172+
173+
fn sub(self, rhs: Self) -> Self {
174+
self - rhs
175+
}
176+
}
177+
178+
impl Sub for i16 {
179+
type Output = Self;
180+
181+
fn sub(self, rhs: Self) -> Self {
182+
self - rhs
183+
}
184+
}
185+
154186
#[lang = "bitor"]
155187
pub trait BitOr<RHS = Self> {
156188
type Output;
@@ -270,6 +302,22 @@ pub trait Neg {
270302
fn neg(self) -> Self::Output;
271303
}
272304

305+
impl Neg for i8 {
306+
type Output = i8;
307+
308+
fn neg(self) -> i8 {
309+
-self
310+
}
311+
}
312+
313+
impl Neg for i16 {
314+
type Output = i16;
315+
316+
fn neg(self) -> i16 {
317+
-self
318+
}
319+
}
320+
273321
impl Neg for isize {
274322
type Output = isize;
275323

example/mini_core_hello_world.rs

+17
Original file line numberDiff line numberDiff line change
@@ -236,4 +236,21 @@ fn main() {
236236
unsafe { assert_eq!(ABC as usize, 0); }
237237

238238
&mut (|| Some(0 as *const ())) as &mut FnMut() -> Option<*const ()>;
239+
240+
// checked binops
241+
let zeroi8 = 0i8;
242+
let oneu8 = 1u8;
243+
let onei8 = 1i8;
244+
zeroi8 - 1;
245+
oneu8 - 1;
246+
zeroi8 - -2i8;
247+
#[allow(unreachable_code)]
248+
{
249+
if false {
250+
let minustwoi8 = -2i8;
251+
oneu8 + 255;
252+
onei8 + 127;
253+
minustwoi8 - 127;
254+
}
255+
}
239256
}

src/base.rs

+54-11
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
241241
} else {
242242
fx.bcx.ins().brz(cond, target, &[]);
243243
};
244-
trap_panic(fx, format!("[panic] Assert {:?} failed.", msg));
244+
trap_panic(fx, format!("[panic] Assert {:?} failed at {:?}.", msg, bb_data.terminator().source_info.span));
245245
}
246246

247247
TerminatorKind::SwitchInt {
@@ -948,17 +948,62 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
948948

949949
let lhs = in_lhs.load_scalar(fx);
950950
let rhs = in_rhs.load_scalar(fx);
951-
let res = match bin_op {
952-
BinOp::Add => fx.bcx.ins().iadd(lhs, rhs),
953-
BinOp::Sub => fx.bcx.ins().isub(lhs, rhs),
954-
BinOp::Mul => fx.bcx.ins().imul(lhs, rhs),
955-
BinOp::Shl => fx.bcx.ins().ishl(lhs, rhs),
951+
let (res, has_overflow) = match bin_op {
952+
BinOp::Add => {
953+
/*let (val, c_out) = fx.bcx.ins().iadd_cout(lhs, rhs);
954+
(val, c_out)*/
955+
// FIXME(CraneStation/cranelift#849) legalize iadd_cout for i8 and i16
956+
let val = fx.bcx.ins().iadd(lhs, rhs);
957+
let has_overflow = if !signed {
958+
fx.bcx.ins().icmp(IntCC::UnsignedLessThan, val, lhs)
959+
} else {
960+
let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
961+
let slt = fx.bcx.ins().icmp(IntCC::SignedLessThan, val, lhs);
962+
fx.bcx.ins().bxor(rhs_is_negative, slt)
963+
};
964+
(val, has_overflow)
965+
}
966+
BinOp::Sub => {
967+
/*let (val, b_out) = fx.bcx.ins().isub_bout(lhs, rhs);
968+
(val, b_out)*/
969+
// FIXME(CraneStation/cranelift#849) legalize isub_bout for i8 and i16
970+
let val = fx.bcx.ins().isub(lhs, rhs);
971+
let has_overflow = if !signed {
972+
fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, val, lhs)
973+
} else {
974+
let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
975+
let sgt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, val, lhs);
976+
fx.bcx.ins().bxor(rhs_is_negative, sgt)
977+
};
978+
(val, has_overflow)
979+
}
980+
BinOp::Mul => {
981+
let val = fx.bcx.ins().imul(lhs, rhs);
982+
/*let val_hi = if !signed {
983+
fx.bcx.ins().umulhi(lhs, rhs)
984+
} else {
985+
fx.bcx.ins().smulhi(lhs, rhs)
986+
};
987+
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, 0);*/
988+
// TODO: check for overflow
989+
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
990+
(val, has_overflow)
991+
}
992+
BinOp::Shl => {
993+
let val = fx.bcx.ins().ishl(lhs, rhs);
994+
// TODO: check for overflow
995+
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
996+
(val, has_overflow)
997+
}
956998
BinOp::Shr => {
957-
if !signed {
999+
let val = if !signed {
9581000
fx.bcx.ins().ushr(lhs, rhs)
9591001
} else {
9601002
fx.bcx.ins().sshr(lhs, rhs)
961-
}
1003+
};
1004+
// TODO: check for overflow
1005+
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
1006+
(val, has_overflow)
9621007
}
9631008
_ => bug!(
9641009
"binop {:?} on checked int/uint lhs: {:?} rhs: {:?}",
@@ -968,9 +1013,7 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
9681013
),
9691014
};
9701015

971-
// TODO: check for overflow
972-
let has_overflow = fx.bcx.ins().iconst(types::I8, 0);
973-
1016+
let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);
9741017
let out_place = CPlace::new_stack_slot(fx, out_ty);
9751018
let out_layout = out_place.layout();
9761019
out_place.write_cvalue(fx, CValue::by_val_pair(res, has_overflow, out_layout));

0 commit comments

Comments
 (0)