Skip to content

Commit dcb64b5

Browse files
committed
represent fat ptr operands as 2 separate pointers
this does add some complexity, but to do otherwise would require unsized lvalues to have their own allocas, which would be ugly.
1 parent 602cf7e commit dcb64b5

File tree

9 files changed

+431
-212
lines changed

9 files changed

+431
-212
lines changed

src/librustc_trans/trans/base.rs

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,49 @@ pub fn bin_op_to_fcmp_predicate(ccx: &CrateContext, op: hir::BinOp_)
312312
}
313313
}
314314

315+
pub fn compare_fat_ptrs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
316+
lhs_addr: ValueRef,
317+
lhs_extra: ValueRef,
318+
rhs_addr: ValueRef,
319+
rhs_extra: ValueRef,
320+
_t: Ty<'tcx>,
321+
op: hir::BinOp_,
322+
debug_loc: DebugLoc)
323+
-> ValueRef {
324+
match op {
325+
hir::BiEq => {
326+
let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc);
327+
let extra_eq = ICmp(bcx, llvm::IntEQ, lhs_extra, rhs_extra, debug_loc);
328+
And(bcx, addr_eq, extra_eq, debug_loc)
329+
}
330+
hir::BiNe => {
331+
let addr_eq = ICmp(bcx, llvm::IntNE, lhs_addr, rhs_addr, debug_loc);
332+
let extra_eq = ICmp(bcx, llvm::IntNE, lhs_extra, rhs_extra, debug_loc);
333+
Or(bcx, addr_eq, extra_eq, debug_loc)
334+
}
335+
hir::BiLe | hir::BiLt | hir::BiGe | hir::BiGt => {
336+
// a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1)
337+
let (op, strict_op) = match op {
338+
hir::BiLt => (llvm::IntULT, llvm::IntULT),
339+
hir::BiLe => (llvm::IntULE, llvm::IntULT),
340+
hir::BiGt => (llvm::IntUGT, llvm::IntUGT),
341+
hir::BiGe => (llvm::IntUGE, llvm::IntUGT),
342+
_ => unreachable!()
343+
};
344+
345+
let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc);
346+
let extra_op = ICmp(bcx, op, lhs_extra, rhs_extra, debug_loc);
347+
let addr_eq_extra_op = And(bcx, addr_eq, extra_op, debug_loc);
348+
349+
let addr_strict = ICmp(bcx, strict_op, lhs_addr, rhs_addr, debug_loc);
350+
Or(bcx, addr_strict, addr_eq_extra_op, debug_loc)
351+
}
352+
_ => {
353+
bcx.tcx().sess.bug("unexpected fat ptr binop");
354+
}
355+
}
356+
}
357+
315358
pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
316359
lhs: ValueRef,
317360
rhs: ValueRef,
@@ -342,39 +385,10 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
342385

343386
let rhs_addr = Load(bcx, GEPi(bcx, rhs, &[0, abi::FAT_PTR_ADDR]));
344387
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-
}
388+
compare_fat_ptrs(bcx,
389+
lhs_addr, lhs_extra,
390+
rhs_addr, rhs_extra,
391+
t, op, debug_loc)
378392
}
379393
ty::TyInt(_) => {
380394
ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, true), lhs, rhs, debug_loc)
@@ -883,6 +897,25 @@ pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t
883897
}
884898
}
885899

900+
pub fn store_fat_ptr<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
901+
data: ValueRef,
902+
extra: ValueRef,
903+
dst: ValueRef,
904+
_ty: Ty<'tcx>) {
905+
// FIXME: emit metadata
906+
Store(cx, data, expr::get_dataptr(cx, dst));
907+
Store(cx, extra, expr::get_meta(cx, dst));
908+
}
909+
910+
pub fn load_fat_ptr<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
911+
src: ValueRef,
912+
_ty: Ty<'tcx>) -> (ValueRef, ValueRef)
913+
{
914+
// FIXME: emit metadata
915+
(Load(cx, expr::get_dataptr(cx, src)),
916+
Load(cx, expr::get_meta(cx, src)))
917+
}
918+
886919
pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
887920
if ty.is_bool() {
888921
ZExt(bcx, val, Type::i8(bcx.ccx()))

src/librustc_trans/trans/mir/analyze.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,15 @@ pub fn lvalue_temps<'bcx,'tcx>(bcx: Block<'bcx,'tcx>,
2727
for (index, temp_decl) in mir.temp_decls.iter().enumerate() {
2828
let ty = bcx.monomorphize(&temp_decl.ty);
2929
debug!("temp {:?} has type {:?}", index, ty);
30-
if
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)
30+
if ty.is_scalar() ||
31+
ty.is_unique() ||
32+
ty.is_region_ptr() ||
33+
ty.is_simd()
3634
{
3735
// These sorts of types are immediates that we can store
3836
// in an ValueRef without an alloca.
39-
assert!(common::type_is_immediate(bcx.ccx(), ty));
37+
assert!(common::type_is_immediate(bcx.ccx(), ty) ||
38+
common::type_is_fat_ptr(bcx.tcx(), ty));
4039
} else {
4140
// These sorts of types require an alloca. Note that
4241
// type_is_immediate() may *still* be true, particularly

src/librustc_trans/trans/mir/block.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
4343
let cond = self.trans_operand(bcx, cond);
4444
let lltrue = self.llblock(true_bb);
4545
let llfalse = self.llblock(false_bb);
46-
build::CondBr(bcx, cond.llval, lltrue, llfalse, DebugLoc::None);
46+
build::CondBr(bcx, cond.immediate(), lltrue, llfalse, DebugLoc::None);
4747
}
4848

4949
mir::Terminator::Switch { .. } => {
@@ -55,7 +55,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
5555
let discr = build::Load(bcx, self.trans_lvalue(bcx, discr).llval);
5656
let switch = build::Switch(bcx, discr, self.llblock(*otherwise), values.len());
5757
for (value, target) in values.iter().zip(targets) {
58-
let llval = self.trans_constval(bcx, value, switch_ty);
58+
let llval = self.trans_constval(bcx, value, switch_ty).immediate();
5959
let llbb = self.llblock(*target);
6060
build::AddCase(switch, llval, llbb)
6161
}

src/librustc_trans/trans/mir/constant.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,39 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use llvm::ValueRef;
1211
use middle::ty::Ty;
1312
use rustc::middle::const_eval::ConstVal;
1413
use rustc_mir::repr as mir;
1514
use trans::consts::{self, TrueConst};
1615
use trans::common::{self, Block};
16+
use trans::common::{C_bool, C_bytes, C_floating_f64, C_integral, C_str_slice};
1717
use trans::type_of;
1818

19+
use super::operand::{OperandRef, OperandValue};
1920
use super::MirContext;
2021

2122
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
2223
pub fn trans_constval(&mut self,
2324
bcx: Block<'bcx, 'tcx>,
2425
cv: &ConstVal,
2526
ty: Ty<'tcx>)
26-
-> ValueRef
27+
-> OperandRef<'tcx>
2728
{
2829
let ccx = bcx.ccx();
2930
let llty = type_of::type_of(ccx, ty);
30-
match *cv {
31-
ConstVal::Float(v) => common::C_floating_f64(v, llty),
32-
ConstVal::Bool(v) => common::C_bool(ccx, v),
33-
ConstVal::Int(v) => common::C_integral(llty, v as u64, true),
34-
ConstVal::Uint(v) => common::C_integral(llty, v, false),
35-
ConstVal::Str(ref v) => common::C_str_slice(ccx, v.clone()),
36-
ConstVal::ByteStr(ref v) => consts::addr_of(ccx,
37-
common::C_bytes(ccx, v),
38-
1,
39-
"byte_str"),
31+
let val = match *cv {
32+
ConstVal::Float(v) => OperandValue::Imm(C_floating_f64(v, llty)),
33+
ConstVal::Bool(v) => OperandValue::Imm(C_bool(ccx, v)),
34+
ConstVal::Int(v) => OperandValue::Imm(C_integral(llty, v as u64, true)),
35+
ConstVal::Uint(v) => OperandValue::Imm(C_integral(llty, v, false)),
36+
ConstVal::Str(ref v) => OperandValue::Imm(C_str_slice(ccx, v.clone())),
37+
ConstVal::ByteStr(ref v) => {
38+
OperandValue::Imm(consts::addr_of(ccx,
39+
C_bytes(ccx, v),
40+
1,
41+
"byte_str"))
42+
}
43+
4044
ConstVal::Struct(id) | ConstVal::Tuple(id) => {
4145
let expr = bcx.tcx().map.expect_expr(id);
4246
let (llval, _) = match consts::const_expr(ccx,
@@ -47,18 +51,26 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
4751
Ok(v) => v,
4852
Err(_) => panic!("constant eval failure"),
4953
};
50-
llval
54+
if common::type_is_immediate(bcx.ccx(), ty) {
55+
OperandValue::Imm(llval)
56+
} else {
57+
OperandValue::Ref(llval)
58+
}
5159
}
5260
ConstVal::Function(_) => {
5361
unimplemented!()
5462
}
63+
};
64+
OperandRef {
65+
ty: ty,
66+
val: val
5567
}
5668
}
5769

5870
pub fn trans_constant(&mut self,
5971
bcx: Block<'bcx, 'tcx>,
6072
constant: &mir::Constant<'tcx>)
61-
-> ValueRef
73+
-> OperandRef<'tcx>
6274
{
6375
let constant_ty = bcx.monomorphize(&constant.ty);
6476
match constant.literal {

src/librustc_trans/trans/mir/lvalue.rs

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ use trans::build;
1818
use trans::common::{self, Block};
1919
use trans::debuginfo::DebugLoc;
2020
use trans::machine;
21-
use trans::tvec;
21+
22+
use std::ptr;
2223

2324
use super::{MirContext, TempRef};
2425

@@ -27,13 +28,16 @@ pub struct LvalueRef<'tcx> {
2728
/// Pointer to the contents of the lvalue
2829
pub llval: ValueRef,
2930

31+
/// This lvalue's extra data if it is unsized, or null
32+
pub llextra: ValueRef,
33+
3034
/// Monomorphized type of this lvalue, including variant information
3135
pub ty: LvalueTy<'tcx>,
3236
}
3337

3438
impl<'tcx> LvalueRef<'tcx> {
35-
pub fn new(llval: ValueRef, lvalue_ty: LvalueTy<'tcx>) -> LvalueRef<'tcx> {
36-
LvalueRef { llval: llval, ty: lvalue_ty }
39+
pub fn new_sized(llval: ValueRef, lvalue_ty: LvalueTy<'tcx>) -> LvalueRef<'tcx> {
40+
LvalueRef { llval: llval, llextra: ptr::null_mut(), ty: lvalue_ty }
3741
}
3842

3943
pub fn alloca<'bcx>(bcx: Block<'bcx, 'tcx>,
@@ -42,11 +46,18 @@ impl<'tcx> LvalueRef<'tcx> {
4246
-> LvalueRef<'tcx>
4347
{
4448
let lltemp = base::alloc_ty(bcx, ty, name);
45-
LvalueRef::new(lltemp, LvalueTy::from_ty(ty))
49+
LvalueRef::new_sized(lltemp, LvalueTy::from_ty(ty))
4650
}
4751
}
4852

4953
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
54+
pub fn lvalue_len(&mut self,
55+
_bcx: Block<'bcx, 'tcx>,
56+
_lvalue: LvalueRef<'tcx>)
57+
-> ValueRef {
58+
unimplemented!()
59+
}
60+
5061
pub fn trans_lvalue(&mut self,
5162
bcx: Block<'bcx, 'tcx>,
5263
lvalue: &mir::Lvalue<'tcx>)
@@ -72,15 +83,20 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
7283
mir::Lvalue::ReturnPointer => {
7384
let return_ty = bcx.monomorphize(&self.mir.return_ty);
7485
let llval = fcx.get_ret_slot(bcx, return_ty, "return");
75-
LvalueRef::new(llval, LvalueTy::from_ty(return_ty.unwrap()))
86+
LvalueRef::new_sized(llval, LvalueTy::from_ty(return_ty.unwrap()))
7687
}
7788
mir::Lvalue::Projection(ref projection) => {
7889
let tr_base = self.trans_lvalue(bcx, &projection.base);
7990
let projected_ty = tr_base.ty.projection_ty(tcx, &projection.elem);
80-
let llprojected = match projection.elem {
91+
let (llprojected, llextra) = match projection.elem {
8192
mir::ProjectionElem::Deref => {
8293
let base_ty = tr_base.ty.to_ty(tcx);
83-
base::load_ty(bcx, tr_base.llval, base_ty)
94+
if common::type_is_sized(tcx, projected_ty.to_ty(tcx)) {
95+
(base::load_ty(bcx, tr_base.llval, base_ty),
96+
ptr::null_mut())
97+
} else {
98+
base::load_fat_ptr(bcx, tr_base.llval, base_ty)
99+
}
84100
}
85101
mir::ProjectionElem::Field(ref field) => {
86102
let base_ty = tr_base.ty.to_ty(tcx);
@@ -90,44 +106,44 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
90106
LvalueTy::Downcast { adt_def: _, substs: _, variant_index: v } => v,
91107
};
92108
let discr = discr as u64;
93-
adt::trans_field_ptr(bcx, &base_repr, tr_base.llval, discr, field.index())
109+
(adt::trans_field_ptr(bcx, &base_repr, tr_base.llval, discr, field.index()),
110+
if common::type_is_sized(tcx, projected_ty.to_ty(tcx)) {
111+
ptr::null_mut()
112+
} else {
113+
tr_base.llextra
114+
})
94115
}
95116
mir::ProjectionElem::Index(ref index) => {
96-
let base_ty = tr_base.ty.to_ty(tcx);
97117
let index = self.trans_operand(bcx, index);
98-
let llindex = self.prepare_index(bcx, index.llval);
99-
let (llbase, _) = tvec::get_base_and_len(bcx, tr_base.llval, base_ty);
100-
build::InBoundsGEP(bcx, llbase, &[llindex])
118+
let llindex = self.prepare_index(bcx, index.immediate());
119+
(build::InBoundsGEP(bcx, tr_base.llval, &[llindex]),
120+
ptr::null_mut())
101121
}
102122
mir::ProjectionElem::ConstantIndex { offset,
103123
from_end: false,
104124
min_length: _ } => {
105-
let base_ty = tr_base.ty.to_ty(tcx);
106125
let lloffset = common::C_u32(bcx.ccx(), offset);
107126
let llindex = self.prepare_index(bcx, lloffset);
108-
let (llbase, _) = tvec::get_base_and_len(bcx,
109-
tr_base.llval,
110-
base_ty);
111-
build::InBoundsGEP(bcx, llbase, &[llindex])
127+
(build::InBoundsGEP(bcx, tr_base.llval, &[llindex]),
128+
ptr::null_mut())
112129
}
113130
mir::ProjectionElem::ConstantIndex { offset,
114131
from_end: true,
115132
min_length: _ } => {
116133
let lloffset = common::C_u32(bcx.ccx(), offset);
117-
let base_ty = tr_base.ty.to_ty(tcx);
118-
let (llbase, lllen) = tvec::get_base_and_len(bcx,
119-
tr_base.llval,
120-
base_ty);
134+
let lllen = self.lvalue_len(bcx, tr_base);
121135
let llindex = build::Sub(bcx, lllen, lloffset, DebugLoc::None);
122136
let llindex = self.prepare_index(bcx, llindex);
123-
build::InBoundsGEP(bcx, llbase, &[llindex])
137+
(build::InBoundsGEP(bcx, tr_base.llval, &[llindex]),
138+
ptr::null_mut())
124139
}
125140
mir::ProjectionElem::Downcast(..) => {
126-
tr_base.llval
141+
(tr_base.llval, tr_base.llextra)
127142
}
128143
};
129144
LvalueRef {
130145
llval: llprojected,
146+
llextra: llextra,
131147
ty: projected_ty,
132148
}
133149
}

src/librustc_trans/trans/mir/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>,
180180
base::store_ty(bcx, llarg, lltemp, arg_ty);
181181
lltemp
182182
};
183-
LvalueRef::new(llval, LvalueTy::from_ty(arg_ty))
183+
LvalueRef::new_sized(llval, LvalueTy::from_ty(arg_ty))
184184
})
185185
.collect()
186186
}

0 commit comments

Comments
 (0)