Skip to content

Commit 602cf7e

Browse files
committed
MIR: implement fat raw pointer comparisons
The implementation itself only requires changes to trans, but a few additional bugs concerning the handling of fat pointers had to be fixed.
1 parent 3beb159 commit 602cf7e

File tree

6 files changed

+279
-61
lines changed

6 files changed

+279
-61
lines changed

src/librustc_trans/trans/base.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,46 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
336336
ty::TyRawPtr(mt) if common::type_is_sized(bcx.tcx(), mt.ty) => {
337337
ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, false), lhs, rhs, debug_loc)
338338
}
339+
ty::TyRawPtr(_) => {
340+
let lhs_addr = Load(bcx, GEPi(bcx, lhs, &[0, abi::FAT_PTR_ADDR]));
341+
let lhs_extra = Load(bcx, GEPi(bcx, lhs, &[0, abi::FAT_PTR_EXTRA]));
342+
343+
let rhs_addr = Load(bcx, GEPi(bcx, rhs, &[0, abi::FAT_PTR_ADDR]));
344+
let rhs_extra = Load(bcx, GEPi(bcx, rhs, &[0, abi::FAT_PTR_EXTRA]));
345+
346+
match op {
347+
hir::BiEq => {
348+
let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc);
349+
let extra_eq = ICmp(bcx, llvm::IntEQ, lhs_extra, rhs_extra, debug_loc);
350+
And(bcx, addr_eq, extra_eq, debug_loc)
351+
}
352+
hir::BiNe => {
353+
let addr_eq = ICmp(bcx, llvm::IntNE, lhs_addr, rhs_addr, debug_loc);
354+
let extra_eq = ICmp(bcx, llvm::IntNE, lhs_extra, rhs_extra, debug_loc);
355+
Or(bcx, addr_eq, extra_eq, debug_loc)
356+
}
357+
hir::BiLe | hir::BiLt | hir::BiGe | hir::BiGt => {
358+
// a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1)
359+
let (op, strict_op) = match op {
360+
hir::BiLt => (llvm::IntULT, llvm::IntULT),
361+
hir::BiLe => (llvm::IntULE, llvm::IntULT),
362+
hir::BiGt => (llvm::IntUGT, llvm::IntUGT),
363+
hir::BiGe => (llvm::IntUGE, llvm::IntUGT),
364+
_ => unreachable!()
365+
};
366+
367+
let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc);
368+
let extra_op = ICmp(bcx, op, lhs_extra, rhs_extra, debug_loc);
369+
let addr_eq_extra_op = And(bcx, addr_eq, extra_op, debug_loc);
370+
371+
let addr_strict = ICmp(bcx, strict_op, lhs_addr, rhs_addr, debug_loc);
372+
Or(bcx, addr_strict, addr_eq_extra_op, debug_loc)
373+
}
374+
_ => {
375+
bcx.tcx().sess.bug("unexpected fat ptr binop");
376+
}
377+
}
378+
}
339379
ty::TyInt(_) => {
340380
ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, true), lhs, rhs, debug_loc)
341381
}
@@ -828,6 +868,10 @@ pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t
828868
return;
829869
}
830870

871+
debug!("store_ty: {} : {:?} <- {}",
872+
cx.val_to_string(dst), t,
873+
cx.val_to_string(v));
874+
831875
if common::type_is_fat_ptr(cx.tcx(), t) {
832876
Store(cx, ExtractValue(cx, v, abi::FAT_PTR_ADDR), expr::get_dataptr(cx, dst));
833877
Store(cx, ExtractValue(cx, v, abi::FAT_PTR_EXTRA), expr::get_meta(cx, dst));

src/librustc_trans/trans/expr.rs

Lines changed: 9 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,58 +1725,6 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
17251725
}
17261726
}
17271727

1728-
fn trans_fat_ptr_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1729-
binop_expr: &hir::Expr,
1730-
binop_ty: Ty<'tcx>,
1731-
op: hir::BinOp,
1732-
lhs: Datum<'tcx, Rvalue>,
1733-
rhs: Datum<'tcx, Rvalue>)
1734-
-> DatumBlock<'blk, 'tcx, Expr>
1735-
{
1736-
let debug_loc = binop_expr.debug_loc();
1737-
1738-
let lhs_addr = Load(bcx, GEPi(bcx, lhs.val, &[0, abi::FAT_PTR_ADDR]));
1739-
let lhs_extra = Load(bcx, GEPi(bcx, lhs.val, &[0, abi::FAT_PTR_EXTRA]));
1740-
1741-
let rhs_addr = Load(bcx, GEPi(bcx, rhs.val, &[0, abi::FAT_PTR_ADDR]));
1742-
let rhs_extra = Load(bcx, GEPi(bcx, rhs.val, &[0, abi::FAT_PTR_EXTRA]));
1743-
1744-
let val = match op.node {
1745-
hir::BiEq => {
1746-
let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc);
1747-
let extra_eq = ICmp(bcx, llvm::IntEQ, lhs_extra, rhs_extra, debug_loc);
1748-
And(bcx, addr_eq, extra_eq, debug_loc)
1749-
}
1750-
hir::BiNe => {
1751-
let addr_eq = ICmp(bcx, llvm::IntNE, lhs_addr, rhs_addr, debug_loc);
1752-
let extra_eq = ICmp(bcx, llvm::IntNE, lhs_extra, rhs_extra, debug_loc);
1753-
Or(bcx, addr_eq, extra_eq, debug_loc)
1754-
}
1755-
hir::BiLe | hir::BiLt | hir::BiGe | hir::BiGt => {
1756-
// a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1)
1757-
let (op, strict_op) = match op.node {
1758-
hir::BiLt => (llvm::IntULT, llvm::IntULT),
1759-
hir::BiLe => (llvm::IntULE, llvm::IntULT),
1760-
hir::BiGt => (llvm::IntUGT, llvm::IntUGT),
1761-
hir::BiGe => (llvm::IntUGE, llvm::IntUGT),
1762-
_ => unreachable!()
1763-
};
1764-
1765-
let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc);
1766-
let extra_op = ICmp(bcx, op, lhs_extra, rhs_extra, debug_loc);
1767-
let addr_eq_extra_op = And(bcx, addr_eq, extra_op, debug_loc);
1768-
1769-
let addr_strict = ICmp(bcx, strict_op, lhs_addr, rhs_addr, debug_loc);
1770-
Or(bcx, addr_strict, addr_eq_extra_op, debug_loc)
1771-
}
1772-
_ => {
1773-
bcx.tcx().sess.span_bug(binop_expr.span, "unexpected binop");
1774-
}
1775-
};
1776-
1777-
immediate_rvalue_bcx(bcx, val, binop_ty).to_expr_datumblock()
1778-
}
1779-
17801728
fn trans_scalar_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
17811729
binop_expr: &hir::Expr,
17821730
binop_ty: Ty<'tcx>,
@@ -2005,7 +1953,15 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
20051953
if type_is_fat_ptr(ccx.tcx(), lhs.ty) {
20061954
assert!(type_is_fat_ptr(ccx.tcx(), rhs.ty),
20071955
"built-in binary operators on fat pointers are homogeneous");
2008-
trans_fat_ptr_binop(bcx, expr, binop_ty, op, lhs, rhs)
1956+
assert_eq!(binop_ty, bcx.tcx().types.bool);
1957+
let val = base::compare_scalar_types(
1958+
bcx,
1959+
lhs.val,
1960+
rhs.val,
1961+
lhs.ty,
1962+
op.node,
1963+
expr.debug_loc());
1964+
immediate_rvalue_bcx(bcx, val, binop_ty).to_expr_datumblock()
20091965
} else {
20101966
assert!(!type_is_fat_ptr(ccx.tcx(), rhs.ty),
20111967
"built-in binary operators on fat pointers are homogeneous");

src/librustc_trans/trans/mir/analyze.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ pub fn lvalue_temps<'bcx,'tcx>(bcx: Block<'bcx,'tcx>,
2828
let ty = bcx.monomorphize(&temp_decl.ty);
2929
debug!("temp {:?} has type {:?}", index, ty);
3030
if
31-
ty.is_scalar() ||
32-
ty.is_unique() ||
33-
(ty.is_region_ptr() && !common::type_is_fat_ptr(bcx.tcx(), ty)) ||
34-
ty.is_simd()
31+
(ty.is_scalar() ||
32+
ty.is_unique() ||
33+
ty.is_region_ptr() ||
34+
ty.is_simd())
35+
&& !common::type_is_fat_ptr(bcx.tcx(), ty)
3536
{
3637
// These sorts of types are immediates that we can store
3738
// in an ValueRef without an alloca.

src/librustc_trans/trans/mir/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,3 @@ mod lvalue;
192192
mod rvalue;
193193
mod operand;
194194
mod statement;
195-

src/librustc_trans/trans/mir/rvalue.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use llvm::ValueRef;
12-
use rustc::middle::ty::Ty;
12+
use rustc::middle::ty::{self, Ty};
1313
use rustc_front::hir;
1414
use rustc_mir::repr as mir;
1515

@@ -45,6 +45,19 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
4545
bcx
4646
}
4747

48+
mir::Rvalue::Cast(mir::CastKind::Unsize, ref operand, cast_ty) => {
49+
let expr_ty =
50+
bcx.monomorphize(&self.mir.operand_ty(bcx.tcx(), operand));
51+
let cast_ty =
52+
bcx.monomorphize(&cast_ty);
53+
if expr_ty == cast_ty {
54+
debug!("trans_rvalue: trivial unsize at {:?}", expr_ty);
55+
self.trans_operand_into(bcx, lldest, operand);
56+
return bcx;
57+
}
58+
unimplemented!()
59+
}
60+
4861
mir::Rvalue::Cast(..) => {
4962
unimplemented!()
5063
}
@@ -93,7 +106,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
93106
_ => {
94107
assert!(rvalue_creates_operand(rvalue));
95108
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
96-
build::Store(bcx, temp.llval, lldest);
109+
base::store_ty(bcx, temp.llval, lldest, temp.ty);
97110
bcx
98111
}
99112
}
@@ -112,6 +125,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
112125
(bcx, operand)
113126
}
114127

128+
mir::Rvalue::Cast(mir::CastKind::Unsize, _, _) => {
129+
unimplemented!()
130+
}
131+
115132
mir::Rvalue::Cast(..) => {
116133
unimplemented!()
117134
}
@@ -240,7 +257,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
240257
};
241258
(bcx, OperandRef {
242259
llval: llval,
243-
ty: lhs.ty,
260+
ty: type_of_binop(bcx.tcx(), op, lhs.ty, rhs.ty),
244261
})
245262
}
246263

@@ -311,3 +328,31 @@ pub fn rvalue_creates_operand<'tcx>(rvalue: &mir::Rvalue<'tcx>) -> bool {
311328

312329
// (*) this is only true if the type is suitable
313330
}
331+
332+
/// FIXME(nikomatsakis): I don't think this function should go here
333+
fn type_of_binop<'tcx>(
334+
tcx: &ty::ctxt<'tcx>,
335+
op: mir::BinOp,
336+
lhs_ty: Ty<'tcx>,
337+
rhs_ty: Ty<'tcx>)
338+
-> Ty<'tcx>
339+
{
340+
match op {
341+
mir::BinOp::Add | mir::BinOp::Sub |
342+
mir::BinOp::Mul | mir::BinOp::Div | mir::BinOp::Rem |
343+
mir::BinOp::BitXor | mir::BinOp::BitAnd | mir::BinOp::BitOr => {
344+
// these should be integers or floats of the same size. We
345+
// probably want to dump all ops in some intrinsics framework
346+
// someday.
347+
assert_eq!(lhs_ty, rhs_ty);
348+
lhs_ty
349+
}
350+
mir::BinOp::Shl | mir::BinOp::Shr => {
351+
lhs_ty // lhs_ty can be != rhs_ty
352+
}
353+
mir::BinOp::Eq | mir::BinOp::Lt | mir::BinOp::Le |
354+
mir::BinOp::Ne | mir::BinOp::Ge | mir::BinOp::Gt => {
355+
tcx.types.bool
356+
}
357+
}
358+
}

0 commit comments

Comments
 (0)