Add CValue variant ByValPair
This commit is contained in:
parent
65641b8872
commit
d87edae73b
2 changed files with 105 additions and 63 deletions
58
src/base.rs
58
src/base.rs
|
@ -727,15 +727,15 @@ pub fn trans_int_binop<'a, 'tcx: 'a>(
|
||||||
pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
|
pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
|
||||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||||
bin_op: BinOp,
|
bin_op: BinOp,
|
||||||
lhs: CValue<'tcx>,
|
in_lhs: CValue<'tcx>,
|
||||||
rhs: CValue<'tcx>,
|
in_rhs: CValue<'tcx>,
|
||||||
out_ty: Ty<'tcx>,
|
out_ty: Ty<'tcx>,
|
||||||
signed: bool,
|
signed: bool,
|
||||||
) -> CValue<'tcx> {
|
) -> CValue<'tcx> {
|
||||||
if bin_op != BinOp::Shl && bin_op != BinOp::Shr {
|
if bin_op != BinOp::Shl && bin_op != BinOp::Shr {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
lhs.layout().ty,
|
in_lhs.layout().ty,
|
||||||
rhs.layout().ty,
|
in_rhs.layout().ty,
|
||||||
"checked int binop requires lhs and rhs of same type"
|
"checked int binop requires lhs and rhs of same type"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -747,40 +747,32 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = binop_match! {
|
let lhs = in_lhs.load_value(fx);
|
||||||
fx, bin_op, signed, lhs, rhs, res_ty, "checked int/uint";
|
let rhs = in_rhs.load_value(fx);
|
||||||
Add (_) iadd;
|
let res = match bin_op {
|
||||||
Sub (_) isub;
|
BinOp::Add => fx.bcx.ins().iadd(lhs, rhs),
|
||||||
Mul (_) imul;
|
BinOp::Sub => fx.bcx.ins().isub(lhs, rhs),
|
||||||
Div (_) bug;
|
BinOp::Mul => fx.bcx.ins().imul(lhs, rhs),
|
||||||
Rem (_) bug;
|
BinOp::Shl => fx.bcx.ins().ishl(lhs, rhs),
|
||||||
BitXor (_) bug;
|
BinOp::Shr => if !signed {
|
||||||
BitAnd (_) bug;
|
fx.bcx.ins().ushr(lhs, rhs)
|
||||||
BitOr (_) bug;
|
} else {
|
||||||
Shl (_) ishl;
|
fx.bcx.ins().sshr(lhs, rhs)
|
||||||
Shr (false) ushr;
|
},
|
||||||
Shr (true) sshr;
|
_ => bug!(
|
||||||
|
"binop {:?} on checked int/uint lhs: {:?} rhs: {:?}",
|
||||||
Eq (_) bug;
|
bin_op,
|
||||||
Lt (_) bug;
|
in_lhs,
|
||||||
Le (_) bug;
|
in_rhs
|
||||||
Ne (_) bug;
|
),
|
||||||
Ge (_) bug;
|
|
||||||
Gt (_) bug;
|
|
||||||
|
|
||||||
Offset (_) bug;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: check for overflow
|
// TODO: check for overflow
|
||||||
let has_overflow = CValue::const_val(fx, fx.tcx.types.bool, 0);
|
let has_overflow = fx.bcx.ins().iconst(types::I8, 0);
|
||||||
|
|
||||||
let out_place = CPlace::temp(fx, out_ty);
|
let out_place = CPlace::temp(fx, out_ty);
|
||||||
out_place
|
let out_layout = out_place.layout();
|
||||||
.place_field(fx, mir::Field::new(0))
|
out_place.write_cvalue(fx, CValue::ByValPair(res, has_overflow, out_layout));
|
||||||
.write_cvalue(fx, res);
|
|
||||||
out_place
|
|
||||||
.place_field(fx, mir::Field::new(1))
|
|
||||||
.write_cvalue(fx, has_overflow);
|
|
||||||
|
|
||||||
out_place.to_cvalue(fx)
|
out_place.to_cvalue(fx)
|
||||||
}
|
}
|
||||||
|
|
110
src/common.rs
110
src/common.rs
|
@ -82,12 +82,15 @@ fn codegen_field<'a, 'tcx: 'a>(
|
||||||
pub enum CValue<'tcx> {
|
pub enum CValue<'tcx> {
|
||||||
ByRef(Value, TyLayout<'tcx>),
|
ByRef(Value, TyLayout<'tcx>),
|
||||||
ByVal(Value, TyLayout<'tcx>),
|
ByVal(Value, TyLayout<'tcx>),
|
||||||
|
ByValPair(Value, Value, TyLayout<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> CValue<'tcx> {
|
impl<'tcx> CValue<'tcx> {
|
||||||
pub fn layout(&self) -> TyLayout<'tcx> {
|
pub fn layout(&self) -> TyLayout<'tcx> {
|
||||||
match *self {
|
match *self {
|
||||||
CValue::ByRef(_, layout) | CValue::ByVal(_, layout) => layout,
|
CValue::ByRef(_, layout)
|
||||||
|
| CValue::ByVal(_, layout)
|
||||||
|
| CValue::ByValPair(_, _, layout) => layout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +111,19 @@ impl<'tcx> CValue<'tcx> {
|
||||||
.ins()
|
.ins()
|
||||||
.stack_addr(fx.module.pointer_type(), stack_slot, 0)
|
.stack_addr(fx.module.pointer_type(), stack_slot, 0)
|
||||||
}
|
}
|
||||||
|
CValue::ByValPair(value, extra, layout) => {
|
||||||
|
let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
|
||||||
|
kind: StackSlotKind::ExplicitSlot,
|
||||||
|
size: layout.size.bytes() as u32,
|
||||||
|
offset: None,
|
||||||
|
});
|
||||||
|
let base = fx.bcx.ins().stack_addr(types::I64, stack_slot, 0);
|
||||||
|
let a_addr = codegen_field(fx, base, layout, mir::Field::new(0)).0;
|
||||||
|
let b_addr = codegen_field(fx, base, layout, mir::Field::new(1)).0;
|
||||||
|
fx.bcx.ins().store(MemFlags::new(), value, a_addr, 0);
|
||||||
|
fx.bcx.ins().store(MemFlags::new(), extra, b_addr, 0);
|
||||||
|
base
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,6 +139,34 @@ impl<'tcx> CValue<'tcx> {
|
||||||
fx.bcx.ins().load(cton_ty, MemFlags::new(), addr, 0)
|
fx.bcx.ins().load(cton_ty, MemFlags::new(), addr, 0)
|
||||||
}
|
}
|
||||||
CValue::ByVal(value, _layout) => value,
|
CValue::ByVal(value, _layout) => value,
|
||||||
|
CValue::ByValPair(_, _, _layout) => bug!("Please use load_value_pair for ByValPair"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_value_pair<'a>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> (Value, Value)
|
||||||
|
where
|
||||||
|
'tcx: 'a,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
CValue::ByRef(addr, layout) => {
|
||||||
|
assert_eq!(
|
||||||
|
layout.size.bytes(),
|
||||||
|
fx.tcx.data_layout.pointer_size.bytes() * 2
|
||||||
|
);
|
||||||
|
let val1_offset = layout.fields.offset(0).bytes() as i32;
|
||||||
|
let val2_offset = layout.fields.offset(1).bytes() as i32;
|
||||||
|
let val1 =
|
||||||
|
fx.bcx
|
||||||
|
.ins()
|
||||||
|
.load(fx.module.pointer_type(), MemFlags::new(), addr, val1_offset);
|
||||||
|
let val2 =
|
||||||
|
fx.bcx
|
||||||
|
.ins()
|
||||||
|
.load(fx.module.pointer_type(), MemFlags::new(), addr, val2_offset);
|
||||||
|
(val1, val2)
|
||||||
|
}
|
||||||
|
CValue::ByVal(_, _layout) => bug!("Please use load_value for ByVal"),
|
||||||
|
CValue::ByValPair(val1, val2, _layout) => (val1, val2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +174,10 @@ impl<'tcx> CValue<'tcx> {
|
||||||
match self {
|
match self {
|
||||||
CValue::ByRef(value, layout) => (value, layout),
|
CValue::ByRef(value, layout) => (value, layout),
|
||||||
CValue::ByVal(_, _) => bug!("Expected CValue::ByRef, found CValue::ByVal: {:?}", self),
|
CValue::ByVal(_, _) => bug!("Expected CValue::ByRef, found CValue::ByVal: {:?}", self),
|
||||||
|
CValue::ByValPair(_, _, _) => bug!(
|
||||||
|
"Expected CValue::ByRef, found CValue::ByValPair: {:?}",
|
||||||
|
self
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,6 +215,7 @@ impl<'tcx> CValue<'tcx> {
|
||||||
match self {
|
match self {
|
||||||
CValue::ByRef(addr, _) => CValue::ByRef(addr, layout),
|
CValue::ByRef(addr, _) => CValue::ByRef(addr, layout),
|
||||||
CValue::ByVal(val, _) => CValue::ByVal(val, layout),
|
CValue::ByVal(val, _) => CValue::ByVal(val, layout),
|
||||||
|
CValue::ByValPair(val, extra, _) => CValue::ByValPair(val, extra, layout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,37 +311,38 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||||
CPlace::Addr(addr, layout) => {
|
CPlace::Addr(addr, layout) => {
|
||||||
let size = layout.size.bytes() as i32;
|
let size = layout.size.bytes() as i32;
|
||||||
|
|
||||||
if let Some(_) = fx.cton_type(layout.ty) {
|
match from {
|
||||||
let data = from.load_value(fx);
|
CValue::ByVal(val, _layout) => {
|
||||||
fx.bcx.ins().store(MemFlags::new(), data, addr, 0);
|
fx.bcx.ins().store(MemFlags::new(), val, addr, 0);
|
||||||
} else {
|
|
||||||
let from = from.expect_byref();
|
|
||||||
let mut offset = 0;
|
|
||||||
while size - offset >= 8 {
|
|
||||||
let byte = fx.bcx.ins().load(
|
|
||||||
fx.module.pointer_type(),
|
|
||||||
MemFlags::new(),
|
|
||||||
from.0,
|
|
||||||
offset,
|
|
||||||
);
|
|
||||||
fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
|
|
||||||
offset += 8;
|
|
||||||
}
|
}
|
||||||
while size - offset >= 4 {
|
CValue::ByValPair(val1, val2, _layout) => {
|
||||||
let byte = fx
|
let val1_offset = layout.fields.offset(0).bytes() as i32;
|
||||||
.bcx
|
let val2_offset = layout.fields.offset(1).bytes() as i32;
|
||||||
.ins()
|
fx.bcx.ins().store(MemFlags::new(), val1, addr, val1_offset);
|
||||||
.load(types::I32, MemFlags::new(), from.0, offset);
|
fx.bcx.ins().store(MemFlags::new(), val2, addr, val2_offset);
|
||||||
fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
|
|
||||||
offset += 4;
|
|
||||||
}
|
}
|
||||||
while offset < size {
|
CValue::ByRef(from, _layout) => {
|
||||||
let byte = fx
|
let mut offset = 0;
|
||||||
.bcx
|
while size - offset >= 8 {
|
||||||
.ins()
|
let byte = fx.bcx.ins().load(
|
||||||
.load(types::I8, MemFlags::new(), from.0, offset);
|
fx.module.pointer_type(),
|
||||||
fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
|
MemFlags::new(),
|
||||||
offset += 1;
|
from,
|
||||||
|
offset,
|
||||||
|
);
|
||||||
|
fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
|
||||||
|
offset += 8;
|
||||||
|
}
|
||||||
|
while size - offset >= 4 {
|
||||||
|
let byte = fx.bcx.ins().load(types::I32, MemFlags::new(), from, offset);
|
||||||
|
fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
|
||||||
|
offset += 4;
|
||||||
|
}
|
||||||
|
while offset < size {
|
||||||
|
let byte = fx.bcx.ins().load(types::I8, MemFlags::new(), from, offset);
|
||||||
|
fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue