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>(
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
bin_op: BinOp,
|
||||
lhs: CValue<'tcx>,
|
||||
rhs: CValue<'tcx>,
|
||||
in_lhs: CValue<'tcx>,
|
||||
in_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,
|
||||
in_lhs.layout().ty,
|
||||
in_rhs.layout().ty,
|
||||
"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! {
|
||||
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 lhs = in_lhs.load_value(fx);
|
||||
let rhs = in_rhs.load_value(fx);
|
||||
let res = match bin_op {
|
||||
BinOp::Add => fx.bcx.ins().iadd(lhs, rhs),
|
||||
BinOp::Sub => fx.bcx.ins().isub(lhs, rhs),
|
||||
BinOp::Mul => fx.bcx.ins().imul(lhs, rhs),
|
||||
BinOp::Shl => fx.bcx.ins().ishl(lhs, rhs),
|
||||
BinOp::Shr => if !signed {
|
||||
fx.bcx.ins().ushr(lhs, rhs)
|
||||
} else {
|
||||
fx.bcx.ins().sshr(lhs, rhs)
|
||||
},
|
||||
_ => bug!(
|
||||
"binop {:?} on checked int/uint lhs: {:?} rhs: {:?}",
|
||||
bin_op,
|
||||
in_lhs,
|
||||
in_rhs
|
||||
),
|
||||
};
|
||||
|
||||
// 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);
|
||||
out_place
|
||||
.place_field(fx, mir::Field::new(0))
|
||||
.write_cvalue(fx, res);
|
||||
out_place
|
||||
.place_field(fx, mir::Field::new(1))
|
||||
.write_cvalue(fx, has_overflow);
|
||||
let out_layout = out_place.layout();
|
||||
out_place.write_cvalue(fx, CValue::ByValPair(res, has_overflow, out_layout));
|
||||
|
||||
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> {
|
||||
ByRef(Value, TyLayout<'tcx>),
|
||||
ByVal(Value, TyLayout<'tcx>),
|
||||
ByValPair(Value, Value, TyLayout<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> CValue<'tcx> {
|
||||
pub fn layout(&self) -> TyLayout<'tcx> {
|
||||
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()
|
||||
.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)
|
||||
}
|
||||
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 {
|
||||
CValue::ByRef(value, layout) => (value, layout),
|
||||
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 {
|
||||
CValue::ByRef(addr, _) => CValue::ByRef(addr, 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) => {
|
||||
let size = layout.size.bytes() as i32;
|
||||
|
||||
if let Some(_) = fx.cton_type(layout.ty) {
|
||||
let data = from.load_value(fx);
|
||||
fx.bcx.ins().store(MemFlags::new(), data, 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;
|
||||
match from {
|
||||
CValue::ByVal(val, _layout) => {
|
||||
fx.bcx.ins().store(MemFlags::new(), val, addr, 0);
|
||||
}
|
||||
while size - offset >= 4 {
|
||||
let byte = fx
|
||||
.bcx
|
||||
.ins()
|
||||
.load(types::I32, MemFlags::new(), from.0, offset);
|
||||
fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
|
||||
offset += 4;
|
||||
CValue::ByValPair(val1, val2, _layout) => {
|
||||
let val1_offset = layout.fields.offset(0).bytes() as i32;
|
||||
let val2_offset = layout.fields.offset(1).bytes() as i32;
|
||||
fx.bcx.ins().store(MemFlags::new(), val1, addr, val1_offset);
|
||||
fx.bcx.ins().store(MemFlags::new(), val2, addr, val2_offset);
|
||||
}
|
||||
while offset < size {
|
||||
let byte = fx
|
||||
.bcx
|
||||
.ins()
|
||||
.load(types::I8, MemFlags::new(), from.0, offset);
|
||||
fx.bcx.ins().store(MemFlags::new(), byte, addr, offset);
|
||||
offset += 1;
|
||||
CValue::ByRef(from, _layout) => {
|
||||
let mut offset = 0;
|
||||
while size - offset >= 8 {
|
||||
let byte = fx.bcx.ins().load(
|
||||
fx.module.pointer_type(),
|
||||
MemFlags::new(),
|
||||
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