Skip to content

Commit 426c558

Browse files
Move trans_field_ptr and struct_field_ptr to mir/lvalue
1 parent 982b8f4 commit 426c558

File tree

7 files changed

+167
-181
lines changed

7 files changed

+167
-181
lines changed

src/librustc_trans/adt.rs

Lines changed: 0 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,13 @@ 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;
52-
use mir::lvalue::LvalueRef;
5351
use common::*;
5452
use builder::Builder;
55-
use glue;
5653
use base;
5754
use machine;
5855
use monomorphize;
5956
use type_::Type;
6057
use type_of;
61-
use value::Value;
6258

6359
#[derive(Copy, Clone, PartialEq)]
6460
pub enum BranchKind {
@@ -471,163 +467,6 @@ pub fn assert_discr_in_range(min: Disr, max: Disr, discr: Disr) {
471467
}
472468
}
473469

474-
/// Access a field, at a point when the value's case is known.
475-
pub fn trans_field_ptr<'a, 'tcx>(
476-
bcx: &Builder<'a, 'tcx>,
477-
val: LvalueRef<'tcx>,
478-
ix: usize,
479-
) -> ValueRef {
480-
let discr = match val.ty {
481-
LvalueTy::Ty { .. } => 0,
482-
LvalueTy::Downcast { variant_index, .. } => variant_index,
483-
};
484-
let t = val.ty.to_ty(bcx.tcx());
485-
let l = bcx.ccx.layout_of(t);
486-
// Note: if this ever needs to generate conditionals (e.g., if we
487-
// decide to do some kind of cdr-coding-like non-unique repr
488-
// someday), it will need to return a possibly-new bcx as well.
489-
match *l {
490-
layout::Univariant { ref variant, .. } => {
491-
assert_eq!(discr, 0);
492-
struct_field_ptr(bcx, &variant,
493-
&compute_fields(bcx.ccx, t, 0, false),
494-
val, ix, false)
495-
}
496-
layout::Vector { count, .. } => {
497-
assert_eq!(discr, 0);
498-
assert!((ix as u64) < count);
499-
bcx.struct_gep(val.llval, ix)
500-
}
501-
layout::General { discr: d, ref variants, .. } => {
502-
let mut fields = compute_fields(bcx.ccx, t, discr, false);
503-
fields.insert(0, d.to_ty(&bcx.tcx(), false));
504-
struct_field_ptr(bcx, &variants[discr],
505-
&fields,
506-
val, ix + 1, true)
507-
}
508-
layout::UntaggedUnion { .. } => {
509-
let fields = compute_fields(bcx.ccx, t, 0, false);
510-
let ty = type_of::in_memory_type_of(bcx.ccx, fields[ix]);
511-
bcx.pointercast(val.llval, ty.ptr_to())
512-
}
513-
layout::RawNullablePointer { nndiscr, .. } |
514-
layout::StructWrappedNullablePointer { nndiscr, .. } if discr as u64 != nndiscr => {
515-
let nullfields = compute_fields(bcx.ccx, t, (1-nndiscr) as usize, false);
516-
// The unit-like case might have a nonzero number of unit-like fields.
517-
// (e.d., Result of Either with (), as one side.)
518-
let ty = type_of::type_of(bcx.ccx, nullfields[ix]);
519-
assert_eq!(machine::llsize_of_alloc(bcx.ccx, ty), 0);
520-
bcx.pointercast(val.llval, ty.ptr_to())
521-
}
522-
layout::RawNullablePointer { nndiscr, .. } => {
523-
let nnty = compute_fields(bcx.ccx, t, nndiscr as usize, false)[0];
524-
assert_eq!(ix, 0);
525-
assert_eq!(discr as u64, nndiscr);
526-
let ty = type_of::type_of(bcx.ccx, nnty);
527-
bcx.pointercast(val.llval, ty.ptr_to())
528-
}
529-
layout::StructWrappedNullablePointer { ref nonnull, nndiscr, .. } => {
530-
assert_eq!(discr as u64, nndiscr);
531-
struct_field_ptr(bcx, &nonnull,
532-
&compute_fields(bcx.ccx, t, discr, false),
533-
val, ix, false)
534-
}
535-
_ => bug!("element access in type without elements: {} represented as {:#?}", t, l)
536-
}
537-
}
538-
539-
fn struct_field_ptr<'a, 'tcx>(
540-
bcx: &Builder<'a, 'tcx>,
541-
st: &layout::Struct,
542-
fields: &Vec<Ty<'tcx>>,
543-
val: LvalueRef,
544-
ix: usize,
545-
needs_cast: bool
546-
) -> ValueRef {
547-
let fty = fields[ix];
548-
let ccx = bcx.ccx;
549-
550-
let ptr_val = if needs_cast {
551-
let fields = st.field_index_by_increasing_offset().map(|i| {
552-
type_of::in_memory_type_of(ccx, fields[i])
553-
}).collect::<Vec<_>>();
554-
let real_ty = Type::struct_(ccx, &fields[..], st.packed);
555-
bcx.pointercast(val.llval, real_ty.ptr_to())
556-
} else {
557-
val.llval
558-
};
559-
560-
// Simple case - we can just GEP the field
561-
// * First field - Always aligned properly
562-
// * Packed struct - There is no alignment padding
563-
// * Field is sized - pointer is properly aligned already
564-
if st.offsets[ix] == layout::Size::from_bytes(0) || st.packed ||
565-
bcx.ccx.shared().type_is_sized(fty) {
566-
return bcx.struct_gep(ptr_val, st.memory_index[ix] as usize);
567-
}
568-
569-
// If the type of the last field is [T] or str, then we don't need to do
570-
// any adjusments
571-
match fty.sty {
572-
ty::TySlice(..) | ty::TyStr => {
573-
return bcx.struct_gep(ptr_val, st.memory_index[ix] as usize);
574-
}
575-
_ => ()
576-
}
577-
578-
// There's no metadata available, log the case and just do the GEP.
579-
if !val.has_extra() {
580-
debug!("Unsized field `{}`, of `{:?}` has no metadata for adjustment",
581-
ix, Value(ptr_val));
582-
return bcx.struct_gep(ptr_val, ix);
583-
}
584-
585-
// We need to get the pointer manually now.
586-
// We do this by casting to a *i8, then offsetting it by the appropriate amount.
587-
// We do this instead of, say, simply adjusting the pointer from the result of a GEP
588-
// because the field may have an arbitrary alignment in the LLVM representation
589-
// anyway.
590-
//
591-
// To demonstrate:
592-
// struct Foo<T: ?Sized> {
593-
// x: u16,
594-
// y: T
595-
// }
596-
//
597-
// The type Foo<Foo<Trait>> is represented in LLVM as { u16, { u16, u8 }}, meaning that
598-
// the `y` field has 16-bit alignment.
599-
600-
let meta = val.llextra;
601-
602-
603-
let offset = st.offsets[ix].bytes();
604-
let unaligned_offset = C_uint(bcx.ccx, offset);
605-
606-
// Get the alignment of the field
607-
let (_, align) = glue::size_and_align_of_dst(bcx, fty, meta);
608-
609-
// Bump the unaligned offset up to the appropriate alignment using the
610-
// following expression:
611-
//
612-
// (unaligned offset + (align - 1)) & -align
613-
614-
// Calculate offset
615-
let align_sub_1 = bcx.sub(align, C_uint(bcx.ccx, 1u64));
616-
let offset = bcx.and(bcx.add(unaligned_offset, align_sub_1),
617-
bcx.neg(align));
618-
619-
debug!("struct_field_ptr: DST field offset: {:?}", Value(offset));
620-
621-
// Cast and adjust pointer
622-
let byte_ptr = bcx.pointercast(ptr_val, Type::i8p(bcx.ccx));
623-
let byte_ptr = bcx.gep(byte_ptr, &[offset]);
624-
625-
// Finally, cast back to the type expected
626-
let ll_fty = type_of::in_memory_type_of(bcx.ccx, fty);
627-
debug!("struct_field_ptr: Field type is {:?}", ll_fty);
628-
bcx.pointercast(byte_ptr, ll_fty.ptr_to())
629-
}
630-
631470
// FIXME this utility routine should be somewhere more general
632471
#[inline]
633472
fn roundup(x: u64, a: u32) -> u64 { let a = a as u64; ((x + (a - 1)) / a) * a }

src/librustc_trans/base.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,8 @@ pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
289289
continue;
290290
}
291291

292-
let src_f = adt::trans_field_ptr(bcx, src, i);
293-
let dst_f = adt::trans_field_ptr(bcx, dst, i);
292+
let src_f = src.trans_field_ptr(bcx, i);
293+
let dst_f = dst.trans_field_ptr(bcx, i);
294294
if src_fty == dst_fty {
295295
memcpy_ty(bcx, dst_f, src_f, src_fty, None);
296296
} else {
@@ -632,7 +632,7 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
632632
let mut llarg_idx = fn_ty.ret.is_indirect() as usize;
633633
let mut arg_idx = 0;
634634
for (i, arg_ty) in sig.inputs().iter().enumerate() {
635-
let lldestptr = adt::trans_field_ptr(&bcx, dest_val, i);
635+
let lldestptr = dest_val.trans_field_ptr(&bcx, i);
636636
let arg = &fn_ty.args[arg_idx];
637637
arg_idx += 1;
638638
if common::type_is_fat_ptr(bcx.ccx, arg_ty) {

src/librustc_trans/glue.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) ->
411411
substs: substs,
412412
variant_index: variant_index,
413413
};
414-
let field_ptr = adt::trans_field_ptr(&cx, av, i);
414+
let field_ptr = av.trans_field_ptr(&cx, i);
415415
drop_ty(&cx, LvalueRef::new_sized_ty(field_ptr, arg));
416416
}
417417
}
@@ -421,7 +421,7 @@ fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) ->
421421
match t.sty {
422422
ty::TyClosure(def_id, substs) => {
423423
for (i, upvar_ty) in substs.upvar_tys(def_id, cx.tcx()).enumerate() {
424-
let llupvar = adt::trans_field_ptr(&cx, ptr, i);
424+
let llupvar = ptr.trans_field_ptr(&cx, i);
425425
drop_ty(&cx, LvalueRef::new_sized_ty(llupvar, upvar_ty));
426426
}
427427
}
@@ -439,7 +439,7 @@ fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) ->
439439
}
440440
ty::TyTuple(ref args) => {
441441
for (i, arg) in args.iter().enumerate() {
442-
let llfld_a = adt::trans_field_ptr(&cx, ptr, i);
442+
let llfld_a = ptr.trans_field_ptr(&cx, i);
443443
drop_ty(&cx, LvalueRef::new_sized_ty(llfld_a, *arg));
444444
}
445445
}
@@ -453,7 +453,7 @@ fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) ->
453453
substs: substs,
454454
variant_index: Disr::from(discr).0 as usize,
455455
};
456-
let llfld_a = adt::trans_field_ptr(&cx, ptr, i);
456+
let llfld_a = ptr.trans_field_ptr(&cx, i);
457457
let ptr = if cx.ccx.shared().type_is_sized(field_ty) {
458458
LvalueRef::new_sized_ty(llfld_a, field_ty)
459459
} else {

src/librustc_trans/intrinsic.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -550,11 +550,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
550550
// etc.
551551
assert!(!bcx.ccx.shared().type_needs_drop(arg_type));
552552
let arg = LvalueRef::new_sized_ty(llarg, arg_type);
553-
(0..contents.len())
554-
.map(|i| {
555-
bcx.load(adt::trans_field_ptr(bcx, arg, i))
556-
})
557-
.collect()
553+
(0..contents.len()).map(|i| bcx.load(arg.trans_field_ptr(bcx, i))).collect()
558554
}
559555
intrinsics::Type::Pointer(_, Some(ref llvm_elem), _) => {
560556
let llvm_elem = one(ty_to_type(bcx.ccx, llvm_elem, &mut false));

src/librustc_trans/mir/block.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -708,9 +708,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
708708
match tuple.val {
709709
Ref(llval) => {
710710
for (n, &ty) in arg_types.iter().enumerate() {
711-
let ptr = adt::trans_field_ptr(
712-
bcx, LvalueRef::new_sized_ty(llval, tuple.ty), n
713-
);
711+
let ptr = LvalueRef::new_sized_ty(llval, tuple.ty);
712+
let ptr = ptr.trans_field_ptr(bcx, n);
714713
let val = if common::type_is_fat_ptr(bcx.ccx, ty) {
715714
let (lldata, llextra) = base::load_fat_ptr(bcx, ptr, ty);
716715
Pair(lldata, llextra)

0 commit comments

Comments
 (0)