Skip to content

Commit ea0ebe4

Browse files
Change trans_field_ptr to utilize LvalueTy to determine discriminant.
1 parent 8038489 commit ea0ebe4

File tree

7 files changed

+72
-49
lines changed

7 files changed

+72
-49
lines changed

src/librustc_trans/adt.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use std;
4848
use llvm::{ValueRef, True, IntEQ, IntNE};
4949
use rustc::ty::layout;
5050
use rustc::ty::{self, Ty, AdtKind};
51+
use rustc::mir::tcx::LvalueTy;
5152
use mir::lvalue::LvalueRef;
5253
use common::*;
5354
use builder::Builder;
@@ -476,31 +477,33 @@ fn assert_discr_in_range(min: Disr, max: Disr, discr: Disr) {
476477
pub fn trans_field_ptr<'a, 'tcx>(
477478
bcx: &Builder<'a, 'tcx>,
478479
val: LvalueRef<'tcx>,
479-
discr: Disr,
480-
ix: usize
480+
ix: usize,
481481
) -> ValueRef {
482+
let discr = match val.ty {
483+
LvalueTy::Ty { .. } => 0,
484+
LvalueTy::Downcast { variant_index, .. } => variant_index,
485+
};
482486
let t = val.ty.to_ty(bcx.tcx());
483487
let l = bcx.ccx.layout_of(t);
484-
debug!("trans_field_ptr on {} represented as {:#?}", t, l);
485488
// Note: if this ever needs to generate conditionals (e.g., if we
486489
// decide to do some kind of cdr-coding-like non-unique repr
487490
// someday), it will need to return a possibly-new bcx as well.
488491
match *l {
489492
layout::Univariant { ref variant, .. } => {
490-
assert_eq!(discr, Disr(0));
493+
assert_eq!(discr, 0);
491494
struct_field_ptr(bcx, &variant,
492495
&compute_fields(bcx.ccx, t, 0, false),
493496
val, ix, false)
494497
}
495498
layout::Vector { count, .. } => {
496-
assert_eq!(discr.0, 0);
499+
assert_eq!(discr, 0);
497500
assert!((ix as u64) < count);
498501
bcx.struct_gep(val.llval, ix)
499502
}
500503
layout::General { discr: d, ref variants, .. } => {
501-
let mut fields = compute_fields(bcx.ccx, t, discr.0 as usize, false);
504+
let mut fields = compute_fields(bcx.ccx, t, discr, false);
502505
fields.insert(0, d.to_ty(&bcx.tcx(), false));
503-
struct_field_ptr(bcx, &variants[discr.0 as usize],
506+
struct_field_ptr(bcx, &variants[discr],
504507
&fields,
505508
val, ix + 1, true)
506509
}
@@ -510,7 +513,7 @@ pub fn trans_field_ptr<'a, 'tcx>(
510513
bcx.pointercast(val.llval, ty.ptr_to())
511514
}
512515
layout::RawNullablePointer { nndiscr, .. } |
513-
layout::StructWrappedNullablePointer { nndiscr, .. } if discr.0 != nndiscr => {
516+
layout::StructWrappedNullablePointer { nndiscr, .. } if discr as u64 != nndiscr => {
514517
let nullfields = compute_fields(bcx.ccx, t, (1-nndiscr) as usize, false);
515518
// The unit-like case might have a nonzero number of unit-like fields.
516519
// (e.d., Result of Either with (), as one side.)
@@ -521,14 +524,14 @@ pub fn trans_field_ptr<'a, 'tcx>(
521524
layout::RawNullablePointer { nndiscr, .. } => {
522525
let nnty = compute_fields(bcx.ccx, t, nndiscr as usize, false)[0];
523526
assert_eq!(ix, 0);
524-
assert_eq!(discr.0, nndiscr);
527+
assert_eq!(discr as u64, nndiscr);
525528
let ty = type_of::type_of(bcx.ccx, nnty);
526529
bcx.pointercast(val.llval, ty.ptr_to())
527530
}
528531
layout::StructWrappedNullablePointer { ref nonnull, nndiscr, .. } => {
529-
assert_eq!(discr.0, nndiscr);
532+
assert_eq!(discr as u64, nndiscr);
530533
struct_field_ptr(bcx, &nonnull,
531-
&compute_fields(bcx.ccx, t, discr.0 as usize, false),
534+
&compute_fields(bcx.ccx, t, discr, false),
532535
val, ix, false)
533536
}
534537
_ => bug!("element access in type without elements: {} represented as {:#?}", t, l)

src/librustc_trans/base.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use llvm;
3737
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
3838
use middle::lang_items::StartFnLangItem;
3939
use rustc::ty::subst::Substs;
40+
use rustc::mir::tcx::LvalueTy;
4041
use rustc::traits;
4142
use rustc::ty::{self, Ty, TyCtxt};
4243
use rustc::ty::adjustment::CustomCoerceUnsized;
@@ -288,8 +289,8 @@ pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
288289
continue;
289290
}
290291

291-
let src_f = adt::trans_field_ptr(bcx, src, Disr(0), i);
292-
let dst_f = adt::trans_field_ptr(bcx, dst, Disr(0), i);
292+
let src_f = adt::trans_field_ptr(bcx, src, i);
293+
let dst_f = adt::trans_field_ptr(bcx, dst, i);
293294
if src_fty == dst_fty {
294295
memcpy_ty(bcx, dst_f, src_f, src_fty, None);
295296
} else {
@@ -622,11 +623,16 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
622623
bcx.alloca(fn_ty.ret.memory_ty(ccx), "sret_slot")
623624
};
624625
// Can return unsized value
625-
let dest_val = LvalueRef::new_sized_ty(dest, sig.output());
626+
let mut dest_val = LvalueRef::new_sized_ty(dest, sig.output());
627+
dest_val.ty = LvalueTy::Downcast {
628+
adt_def: sig.output().ty_adt_def().unwrap(),
629+
substs: substs,
630+
variant_index: disr.0 as usize,
631+
};
626632
let mut llarg_idx = fn_ty.ret.is_indirect() as usize;
627633
let mut arg_idx = 0;
628634
for (i, arg_ty) in sig.inputs().iter().enumerate() {
629-
let lldestptr = adt::trans_field_ptr(&bcx, dest_val, Disr::from(disr), i);
635+
let lldestptr = adt::trans_field_ptr(&bcx, dest_val, i);
630636
let arg = &fn_ty.args[arg_idx];
631637
arg_idx += 1;
632638
if common::type_is_fat_ptr(bcx.ccx, arg_ty) {

src/librustc_trans/glue.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ use llvm::{ValueRef, get_param};
2020
use middle::lang_items::BoxFreeFnLangItem;
2121
use rustc::ty::subst::{Substs};
2222
use rustc::traits;
23-
use rustc::ty::{self, AdtKind, Ty, TypeFoldable};
23+
use rustc::ty::{self, AdtDef, AdtKind, Ty, TypeFoldable};
2424
use rustc::ty::subst::Kind;
25+
use rustc::mir::tcx::LvalueTy;
2526
use mir::lvalue::LvalueRef;
2627
use adt;
2728
use base::*;
@@ -395,14 +396,22 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
395396

396397
// Iterates through the elements of a structural type, dropping them.
397398
fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) -> Builder<'a, 'tcx> {
398-
fn iter_variant<'a, 'tcx>(cx: &Builder<'a, 'tcx>,
399+
fn iter_variant<'a, 'tcx>(cx: &'a Builder<'a, 'tcx>,
399400
av: LvalueRef<'tcx>,
400-
variant: &'tcx ty::VariantDef,
401-
substs: &Substs<'tcx>) {
401+
adt_def: &'tcx AdtDef,
402+
variant_index: usize,
403+
substs: &'tcx Substs<'tcx>) {
404+
let variant = &adt_def.variants[variant_index];
402405
let tcx = cx.tcx();
403406
for (i, field) in variant.fields.iter().enumerate() {
404407
let arg = monomorphize::field_ty(tcx, substs, field);
405-
let field_ptr = adt::trans_field_ptr(&cx, av, Disr::from(variant.disr_val), i);
408+
let mut av = av.clone();
409+
av.ty = LvalueTy::Downcast {
410+
adt_def: adt_def,
411+
substs: substs,
412+
variant_index: variant_index,
413+
};
414+
let field_ptr = adt::trans_field_ptr(&cx, av, i);
406415
drop_ty(&cx, LvalueRef::new_sized_ty(field_ptr, arg));
407416
}
408417
}
@@ -412,7 +421,7 @@ fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) ->
412421
match t.sty {
413422
ty::TyClosure(def_id, substs) => {
414423
for (i, upvar_ty) in substs.upvar_tys(def_id, cx.tcx()).enumerate() {
415-
let llupvar = adt::trans_field_ptr(&cx, ptr, Disr(0), i);
424+
let llupvar = adt::trans_field_ptr(&cx, ptr, i);
416425
drop_ty(&cx, LvalueRef::new_sized_ty(llupvar, upvar_ty));
417426
}
418427
}
@@ -430,15 +439,21 @@ fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) ->
430439
}
431440
ty::TyTuple(ref args) => {
432441
for (i, arg) in args.iter().enumerate() {
433-
let llfld_a = adt::trans_field_ptr(&cx, ptr, Disr(0), i);
442+
let llfld_a = adt::trans_field_ptr(&cx, ptr, i);
434443
drop_ty(&cx, LvalueRef::new_sized_ty(llfld_a, *arg));
435444
}
436445
}
437446
ty::TyAdt(adt, substs) => match adt.adt_kind() {
438447
AdtKind::Struct => {
439448
let VariantInfo { fields, discr } = VariantInfo::from_ty(cx.tcx(), t, None);
440449
for (i, &Field(_, field_ty)) in fields.iter().enumerate() {
441-
let llfld_a = adt::trans_field_ptr(&cx, ptr, Disr::from(discr), i);
450+
let mut ptr = ptr.clone();
451+
ptr.ty = LvalueTy::Downcast {
452+
adt_def: adt,
453+
substs: substs,
454+
variant_index: Disr::from(discr).0 as usize,
455+
};
456+
let llfld_a = adt::trans_field_ptr(&cx, ptr, i);
442457
let ptr = if cx.ccx.shared().type_is_sized(field_ty) {
443458
LvalueRef::new_sized_ty(llfld_a, field_ty)
444459
} else {
@@ -460,7 +475,7 @@ fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) ->
460475
(adt::BranchKind::Single, None) => {
461476
if n_variants != 0 {
462477
assert!(n_variants == 1);
463-
iter_variant(&cx, ptr, &adt.variants[0], substs);
478+
iter_variant(&cx, ptr, &adt, 0, substs);
464479
}
465480
}
466481
(adt::BranchKind::Switch, Some(lldiscrim_a)) => {
@@ -485,13 +500,13 @@ fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) ->
485500
let llswitch = cx.switch(lldiscrim_a, ret_void_cx.llbb(), n_variants);
486501
let next_cx = cx.build_new_block("enum-iter-next");
487502

488-
for variant in &adt.variants {
503+
for (i, variant) in adt.variants.iter().enumerate() {
489504
let variant_cx_name = format!("enum-iter-variant-{}",
490505
&variant.disr_val.to_string());
491506
let variant_cx = cx.build_new_block(&variant_cx_name);
492507
let case_val = adt::trans_case(&cx, t, Disr::from(variant.disr_val));
493508
variant_cx.add_case(llswitch, case_val, variant_cx.llbb());
494-
iter_variant(&variant_cx, ptr, variant, substs);
509+
iter_variant(&variant_cx, ptr, &adt, i, substs);
495510
variant_cx.br(next_cx.llbb());
496511
}
497512
cx = next_cx;

src/librustc_trans/intrinsic.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use type_of;
2525
use machine;
2626
use type_::Type;
2727
use rustc::ty::{self, Ty};
28-
use Disr;
2928
use rustc::hir;
3029
use syntax::ast;
3130
use syntax::symbol::Symbol;
@@ -553,7 +552,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
553552
let arg = LvalueRef::new_sized_ty(llarg, arg_type);
554553
(0..contents.len())
555554
.map(|i| {
556-
bcx.load(adt::trans_field_ptr(bcx, arg, Disr(0), i))
555+
bcx.load(adt::trans_field_ptr(bcx, arg, i))
557556
})
558557
.collect()
559558
}

src/librustc_trans/mir/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
709709
Ref(llval) => {
710710
for (n, &ty) in arg_types.iter().enumerate() {
711711
let ptr = adt::trans_field_ptr(
712-
bcx, LvalueRef::new_sized_ty(llval, tuple.ty), Disr(0), n
712+
bcx, LvalueRef::new_sized_ty(llval, tuple.ty), n
713713
);
714714
let val = if common::type_is_fat_ptr(bcx.ccx, ty) {
715715
let (lldata, llextra) = base::load_fat_ptr(bcx, ptr, ty);

src/librustc_trans/mir/lvalue.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use consts;
2020
use machine;
2121
use type_of::type_of;
2222
use type_of;
23-
use Disr;
2423

2524
use std::ptr;
2625

@@ -48,6 +47,13 @@ impl<'tcx> LvalueRef<'tcx> {
4847
LvalueRef::new_sized(llval, LvalueTy::from_ty(ty))
4948
}
5049

50+
pub fn new_unsized(llval: ValueRef, llextra: ValueRef, ty: LvalueTy<'tcx>) -> LvalueRef<'tcx> {
51+
LvalueRef {
52+
llval: llval,
53+
llextra: llextra,
54+
ty: ty,
55+
}
56+
}
5157
pub fn new_unsized_ty(llval: ValueRef, llextra: ValueRef, ty: Ty<'tcx>) -> LvalueRef<'tcx> {
5258
LvalueRef {
5359
llval: llval,
@@ -140,26 +146,14 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
140146
let (llprojected, llextra) = match projection.elem {
141147
mir::ProjectionElem::Deref => bug!(),
142148
mir::ProjectionElem::Field(ref field, _) => {
143-
let base_ty = tr_base.ty.to_ty(tcx);
144-
let discr = match tr_base.ty {
145-
LvalueTy::Ty { .. } => 0,
146-
LvalueTy::Downcast { adt_def: _, substs: _, variant_index: v } => v,
147-
};
148-
let discr = discr as u64;
149149
let is_sized = self.ccx.shared().type_is_sized(projected_ty.to_ty(tcx));
150150
let base = if is_sized {
151-
LvalueRef::new_sized_ty(tr_base.llval, base_ty)
152-
} else {
153-
LvalueRef::new_unsized_ty(tr_base.llval, tr_base.llextra, base_ty)
154-
};
155-
let llprojected = adt::trans_field_ptr(bcx, base, Disr(discr),
156-
field.index());
157-
let llextra = if is_sized {
158-
ptr::null_mut()
151+
LvalueRef::new_sized(tr_base.llval, tr_base.ty)
159152
} else {
160-
tr_base.llextra
153+
LvalueRef::new_unsized(tr_base.llval, tr_base.llextra, tr_base.ty)
161154
};
162-
(llprojected, llextra)
155+
let llprojected = adt::trans_field_ptr(bcx, base, field.index());
156+
(llprojected, base.llextra)
163157
}
164158
mir::ProjectionElem::Index(ref index) => {
165159
let index = self.trans_operand(bcx, index);

src/librustc_trans/mir/rvalue.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use llvm::{self, ValueRef};
1212
use rustc::ty::{self, Ty};
1313
use rustc::ty::cast::{CastTy, IntTy};
1414
use rustc::ty::layout::Layout;
15+
use rustc::mir::tcx::LvalueTy;
1516
use rustc::mir;
1617
use middle::lang_items::ExchangeMallocFnLangItem;
1718

@@ -102,17 +103,22 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
102103

103104
mir::Rvalue::Aggregate(ref kind, ref operands) => {
104105
match *kind {
105-
mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
106+
mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => {
106107
let disr = Disr::from(adt_def.variants[variant_index].disr_val);
107108
let dest_ty = dest.ty.to_ty(bcx.tcx());
108109
adt::trans_set_discr(&bcx, dest_ty, dest.llval, Disr::from(disr));
109110
for (i, operand) in operands.iter().enumerate() {
110111
let op = self.trans_operand(&bcx, operand);
111112
// Do not generate stores and GEPis for zero-sized fields.
112113
if !common::type_is_zero_size(bcx.ccx, op.ty) {
113-
let val = LvalueRef::new_sized_ty(dest.llval, dest_ty);
114+
let mut val = LvalueRef::new_sized(dest.llval, dest.ty);
114115
let field_index = active_field_index.unwrap_or(i);
115-
let lldest_i = adt::trans_field_ptr(&bcx, val, disr, field_index);
116+
val.ty = LvalueTy::Downcast {
117+
adt_def: adt_def,
118+
substs: self.monomorphize(&substs),
119+
variant_index: disr.0 as usize,
120+
};
121+
let lldest_i = adt::trans_field_ptr(&bcx, val, field_index);
116122
self.store_operand(&bcx, lldest_i, op, None);
117123
}
118124
}

0 commit comments

Comments
 (0)