Don't crash on checked binops (treated like unchecked ones atm)

This commit is contained in:
bjorn3 2018-08-08 09:34:56 +02:00
parent 5c601f7316
commit 376ec8c258
5 changed files with 76 additions and 23 deletions

View File

@ -18,8 +18,6 @@ $ cargo build
$ rustc -Zcodegen-backend=$(pwd)/target/debug/librustc_codegen_cranelift.so my_crate.rs --crate-type lib -Og
```
> You must compile with `-Og`, because checked binops are not yet supported.
## Building libcore
```bash

View File

@ -2,7 +2,7 @@ cargo build || exit 1
cd examples/
RUSTC="rustc -Zcodegen-backend=$(pwd)/../target/debug/librustc_codegen_cranelift.so -Og -L crate=. --crate-type lib"
RUSTC="rustc -Zcodegen-backend=$(pwd)/../target/debug/librustc_codegen_cranelift.so -L crate=. --crate-type lib"
$RUSTC mini_core.rs --crate-name mini_core &&
$RUSTC example.rs &&

View File

@ -398,7 +398,6 @@ pub fn codegen_call<'a, 'tcx: 'a>(
args[1],
ret.layout().ty,
false,
false,
),
TypeVariants::TyInt(_) => crate::base::trans_int_binop(
fx,
@ -407,7 +406,6 @@ pub fn codegen_call<'a, 'tcx: 'a>(
args[1],
ret.layout().ty,
true,
false,
),
_ => panic!(),
};

View File

@ -313,10 +313,10 @@ fn trans_stmt<'a, 'tcx: 'a>(
trans_bool_binop(fx, *bin_op, lhs, rhs, lval.layout().ty)
}
TypeVariants::TyUint(_) => {
trans_int_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, false, false)
trans_int_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, false)
}
TypeVariants::TyInt(_) => {
trans_int_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, true, false)
trans_int_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, true)
}
TypeVariants::TyFloat(_) => {
trans_float_binop(fx, *bin_op, lhs, rhs, lval.layout().ty)
@ -325,9 +325,9 @@ fn trans_stmt<'a, 'tcx: 'a>(
trans_char_binop(fx, *bin_op, lhs, rhs, lval.layout().ty)
}
TypeVariants::TyRawPtr(..) => {
trans_ptr_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, false)
trans_ptr_binop(fx, *bin_op, lhs, rhs, lval.layout().ty)
}
_ => unimplemented!("bin op {:?} for {:?}", bin_op, ty),
_ => unimplemented!("binop {:?} for {:?}", bin_op, ty),
};
lval.write_cvalue(fx, res);
}
@ -338,14 +338,13 @@ fn trans_stmt<'a, 'tcx: 'a>(
let res = match ty.sty {
TypeVariants::TyUint(_) => {
trans_int_binop(fx, *bin_op, lhs, rhs, ty, false, true)
trans_checked_int_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, false)
}
TypeVariants::TyInt(_) => {
trans_int_binop(fx, *bin_op, lhs, rhs, ty, true, true)
trans_checked_int_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, true)
}
_ => unimplemented!("checked bin op {:?} for {:?}", bin_op, ty),
_ => unimplemented!("checked binop {:?} for {:?}", bin_op, ty),
};
return Err(format!("checked bin op {:?}", bin_op));
lval.write_cvalue(fx, res);
}
Rvalue::UnaryOp(un_op, operand) => {
@ -510,7 +509,7 @@ pub fn trans_get_discriminant<'a, 'tcx: 'a>(
macro_rules! binop_match {
(@single $fx:expr, $bug_fmt:expr, $var:expr, $lhs:expr, $rhs:expr, $ret_ty:expr, bug) => {
bug!("bin op {} on {} lhs: {:?} rhs: {:?}", stringify!($var), $bug_fmt, $lhs, $rhs)
bug!("binop {} on {} lhs: {:?} rhs: {:?}", stringify!($var), $bug_fmt, $lhs, $rhs)
};
(@single $fx:expr, $bug_fmt:expr, $var:expr, $lhs:expr, $rhs:expr, $ret_ty:expr, icmp($cc:ident)) => {{
assert_eq!($fx.tcx.types.bool, $ret_ty);
@ -585,12 +584,14 @@ pub fn trans_int_binop<'a, 'tcx: 'a>(
bin_op: BinOp,
lhs: CValue<'tcx>,
rhs: CValue<'tcx>,
ty: Ty<'tcx>,
out_ty: Ty<'tcx>,
signed: bool,
_checked: bool,
) -> CValue<'tcx> {
let res = binop_match! {
fx, bin_op, signed, lhs, rhs, ty, "int/uint";
if bin_op != BinOp::Shl && bin_op != BinOp::Shr {
assert_eq!(lhs.layout().ty, rhs.layout().ty, "int binop requires lhs and rhs of same type");
}
binop_match! {
fx, bin_op, signed, lhs, rhs, out_ty, "int/uint";
Add (_) iadd;
Sub (_) isub;
Mul (_) imul;
@ -617,10 +618,57 @@ pub fn trans_int_binop<'a, 'tcx: 'a>(
Gt (true) icmp(SignedGreaterThan);
Offset (_) bug;
}
}
fn trans_checked_int_binop<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx>,
bin_op: BinOp,
lhs: CValue<'tcx>,
rhs: CValue<'tcx>,
out_ty: Ty<'tcx>,
signed: bool,
) -> CValue<'tcx> {
if bin_op != BinOp::Shl && bin_op != BinOp::Shr {
assert_eq!(lhs.layout().ty, rhs.layout().ty, "checked int binop requires lhs and rhs of same type");
}
let res_ty = match out_ty.sty {
TypeVariants::TyTuple(tys) => tys[0],
_ => bug!("Checked int binop requires tuple as output, but got {:?}", out_ty),
};
// TODO: return correct value for checked binops
res
let res = binop_match! {
fx, bin_op, signed, lhs, rhs, res_ty, "checked int/uint";
Add (_) iadd;
Sub (_) isub;
Mul (_) imul;
Div (_) bug;
Rem (_) bug;
BitXor (_) bug;
BitAnd (_) bug;
BitOr (_) bug;
Shl (_) ishl;
Shr (false) ushr;
Shr (true) sshr;
Eq (_) bug;
Lt (_) bug;
Le (_) bug;
Ne (_) bug;
Ge (_) bug;
Gt (_) bug;
Offset (_) bug;
};
let has_overflow = CValue::const_val(fx, fx.tcx.types.bool, 0);
let out_place = CPlace::temp(fx, out_ty);
out_place.place_field(fx, mir::Field::new(0)).write_cvalue(fx, res);
println!("abc");
out_place.place_field(fx, mir::Field::new(1)).write_cvalue(fx, has_overflow);
out_place.to_cvalue(fx)
}
fn trans_float_binop<'a, 'tcx: 'a>(
@ -703,7 +751,6 @@ fn trans_ptr_binop<'a, 'tcx: 'a>(
lhs: CValue<'tcx>,
rhs: CValue<'tcx>,
ty: Ty<'tcx>,
_checked: bool,
) -> CValue<'tcx> {
binop_match! {
fx, bin_op, false, lhs, rhs, ty, "ptr";

View File

@ -133,8 +133,8 @@ impl<'tcx> CValue<'tcx> {
pub fn expect_byref(self) -> (Value, TyLayout<'tcx>) {
match self {
CValue::ByRef(value, layout) => (value, layout),
CValue::ByVal(_, _) => bug!("Expected CValue::ByRef, found CValue::ByVal"),
CValue::Func(_, _) => bug!("Expected CValue::ByRef, found CValue::Func"),
CValue::ByVal(_, _) => bug!("Expected CValue::ByRef, found CValue::ByVal: {:?}", self),
CValue::Func(_, _) => bug!("Expected CValue::ByRef, found CValue::Func: {:?}", self),
}
}
@ -187,6 +187,16 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
}
}
pub fn temp(fx: &mut FunctionCx<'a, 'tcx>, ty: Ty<'tcx>) -> CPlace<'tcx> {
let layout = fx.layout_of(ty);
let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
kind: StackSlotKind::ExplicitSlot,
size: layout.size.bytes() as u32,
offset: None,
});
CPlace::Addr(fx.bcx.ins().stack_addr(types::I64, stack_slot, 0), layout)
}
pub fn from_stack_slot(
fx: &mut FunctionCx<'a, 'tcx>,
stack_slot: StackSlot,