Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional cleanup to rustc_trans #38756

Merged
merged 18 commits into from
Jan 5, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 12 additions & 37 deletions src/librustc_trans/adt.rs
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@ use std;
use llvm::{ValueRef, True, IntEQ, IntNE};
use rustc::ty::layout;
use rustc::ty::{self, Ty, AdtKind};
use mir::lvalue::LvalueRef;
use common::*;
use builder::Builder;
use glue;
@@ -64,32 +65,6 @@ pub enum BranchKind {
Single
}

#[derive(Copy, Clone)]
pub struct MaybeSizedValue {
pub value: ValueRef,
pub meta: ValueRef,
}

impl MaybeSizedValue {
pub fn sized(value: ValueRef) -> MaybeSizedValue {
MaybeSizedValue {
value: value,
meta: std::ptr::null_mut()
}
}

pub fn unsized_(value: ValueRef, meta: ValueRef) -> MaybeSizedValue {
MaybeSizedValue {
value: value,
meta: meta
}
}

pub fn has_meta(&self) -> bool {
!self.meta.is_null()
}
}

/// Given an enum, struct, closure, or tuple, extracts fields.
/// Treats closures as a struct with one variant.
/// `empty_if_no_variants` is a switch to deal with empty enums.
@@ -500,11 +475,11 @@ fn assert_discr_in_range(min: Disr, max: Disr, discr: Disr) {
/// Access a field, at a point when the value's case is known.
pub fn trans_field_ptr<'a, 'tcx>(
bcx: &Builder<'a, 'tcx>,
t: Ty<'tcx>,
val: MaybeSizedValue,
val: LvalueRef<'tcx>,
discr: Disr,
ix: usize
) -> ValueRef {
let t = val.ty.to_ty(bcx.tcx());
let l = bcx.ccx.layout_of(t);
debug!("trans_field_ptr on {} represented as {:#?}", t, l);
// Note: if this ever needs to generate conditionals (e.g., if we
@@ -520,7 +495,7 @@ pub fn trans_field_ptr<'a, 'tcx>(
layout::Vector { count, .. } => {
assert_eq!(discr.0, 0);
assert!((ix as u64) < count);
bcx.struct_gep(val.value, ix)
bcx.struct_gep(val.llval, ix)
}
layout::General { discr: d, ref variants, .. } => {
let mut fields = compute_fields(bcx.ccx, t, discr.0 as usize, false);
@@ -532,7 +507,7 @@ pub fn trans_field_ptr<'a, 'tcx>(
layout::UntaggedUnion { .. } => {
let fields = compute_fields(bcx.ccx, t, 0, false);
let ty = type_of::in_memory_type_of(bcx.ccx, fields[ix]);
bcx.pointercast(val.value, ty.ptr_to())
bcx.pointercast(val.llval, ty.ptr_to())
}
layout::RawNullablePointer { nndiscr, .. } |
layout::StructWrappedNullablePointer { nndiscr, .. } if discr.0 != nndiscr => {
@@ -541,14 +516,14 @@ pub fn trans_field_ptr<'a, 'tcx>(
// (e.d., Result of Either with (), as one side.)
let ty = type_of::type_of(bcx.ccx, nullfields[ix]);
assert_eq!(machine::llsize_of_alloc(bcx.ccx, ty), 0);
bcx.pointercast(val.value, ty.ptr_to())
bcx.pointercast(val.llval, ty.ptr_to())
}
layout::RawNullablePointer { nndiscr, .. } => {
let nnty = compute_fields(bcx.ccx, t, nndiscr as usize, false)[0];
assert_eq!(ix, 0);
assert_eq!(discr.0, nndiscr);
let ty = type_of::type_of(bcx.ccx, nnty);
bcx.pointercast(val.value, ty.ptr_to())
bcx.pointercast(val.llval, ty.ptr_to())
}
layout::StructWrappedNullablePointer { ref nonnull, nndiscr, .. } => {
assert_eq!(discr.0, nndiscr);
@@ -564,7 +539,7 @@ fn struct_field_ptr<'a, 'tcx>(
bcx: &Builder<'a, 'tcx>,
st: &layout::Struct,
fields: &Vec<Ty<'tcx>>,
val: MaybeSizedValue,
val: LvalueRef,
ix: usize,
needs_cast: bool
) -> ValueRef {
@@ -576,9 +551,9 @@ fn struct_field_ptr<'a, 'tcx>(
type_of::in_memory_type_of(ccx, fields[i])
}).collect::<Vec<_>>();
let real_ty = Type::struct_(ccx, &fields[..], st.packed);
bcx.pointercast(val.value, real_ty.ptr_to())
bcx.pointercast(val.llval, real_ty.ptr_to())
} else {
val.value
val.llval
};

// Simple case - we can just GEP the field
@@ -600,7 +575,7 @@ fn struct_field_ptr<'a, 'tcx>(
}

// There's no metadata available, log the case and just do the GEP.
if !val.has_meta() {
if !val.has_extra() {
debug!("Unsized field `{}`, of `{:?}` has no metadata for adjustment",
ix, Value(ptr_val));
return bcx.struct_gep(ptr_val, ix);
@@ -621,7 +596,7 @@ fn struct_field_ptr<'a, 'tcx>(
// The type Foo<Foo<Trait>> is represented in LLVM as { u16, { u16, u8 }}, meaning that
// the `y` field has 16-bit alignment.

let meta = val.meta;
let meta = val.llextra;


let offset = st.offsets[ix].bytes();
14 changes: 8 additions & 6 deletions src/librustc_trans/base.rs
Original file line number Diff line number Diff line change
@@ -47,6 +47,7 @@ use session::config::{self, NoDebugInfo};
use rustc_incremental::IncrementalHashesMap;
use session::{self, DataTypeKind, Session};
use abi::{self, Abi, FnType};
use mir::lvalue::LvalueRef;
use adt;
use attributes;
use builder::Builder;
@@ -278,17 +279,17 @@ pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
monomorphize::field_ty(bcx.tcx(), substs_b, f)
});

let src = adt::MaybeSizedValue::sized(src);
let dst = adt::MaybeSizedValue::sized(dst);
let src = LvalueRef::new_sized_ty(src, src_ty);
let dst = LvalueRef::new_sized_ty(dst, dst_ty);

let iter = src_fields.zip(dst_fields).enumerate();
for (i, (src_fty, dst_fty)) in iter {
if type_is_zero_size(bcx.ccx, dst_fty) {
continue;
}

let src_f = adt::trans_field_ptr(bcx, src_ty, src, Disr(0), i);
let dst_f = adt::trans_field_ptr(bcx, dst_ty, dst, Disr(0), i);
let src_f = adt::trans_field_ptr(bcx, src, Disr(0), i);
let dst_f = adt::trans_field_ptr(bcx, dst, Disr(0), i);
if src_fty == dst_fty {
memcpy_ty(bcx, dst_f, src_f, src_fty, None);
} else {
@@ -620,11 +621,12 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// final ret value
bcx.alloca(fn_ty.ret.memory_ty(ccx), "sret_slot")
};
let dest_val = adt::MaybeSizedValue::sized(dest); // Can return unsized value
// Can return unsized value
let dest_val = LvalueRef::new_sized_ty(dest, sig.output());
let mut llarg_idx = fn_ty.ret.is_indirect() as usize;
let mut arg_idx = 0;
for (i, arg_ty) in sig.inputs().iter().enumerate() {
let lldestptr = adt::trans_field_ptr(&bcx, sig.output(), dest_val, Disr::from(disr), i);
let lldestptr = adt::trans_field_ptr(&bcx, dest_val, Disr::from(disr), i);
let arg = &fn_ty.args[arg_idx];
arg_idx += 1;
if common::type_is_fat_ptr(bcx.ccx, arg_ty) {
4 changes: 2 additions & 2 deletions src/librustc_trans/callee.rs
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ use base;
use builder::Builder;
use common::{self, CrateContext, SharedCrateContext};
use cleanup::CleanupScope;
use adt::MaybeSizedValue;
use mir::lvalue::LvalueRef;
use consts;
use declare;
use value::Value;
@@ -364,7 +364,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
// Call the by-ref closure body with `self` in a cleanup scope,
// to drop `self` when the body returns, or in case it unwinds.
let self_scope = CleanupScope::schedule_drop_mem(
&bcx, MaybeSizedValue::sized(llenv), closure_ty
&bcx, LvalueRef::new_sized_ty(llenv, closure_ty)
);

let llfn = callee.reify(bcx.ccx);
29 changes: 18 additions & 11 deletions src/librustc_trans/cleanup.rs
Original file line number Diff line number Diff line change
@@ -20,12 +20,12 @@
use llvm::BasicBlockRef;
use base;
use adt::MaybeSizedValue;
use mir::lvalue::LvalueRef;
use rustc::mir::tcx::LvalueTy;
use builder::Builder;
use common::Funclet;
use glue;
use type_::Type;
use rustc::ty::Ty;

pub struct CleanupScope<'tcx> {
// Cleanup to run upon scope exit.
@@ -37,14 +37,13 @@ pub struct CleanupScope<'tcx> {

#[derive(Copy, Clone)]
pub struct DropValue<'tcx> {
val: MaybeSizedValue,
ty: Ty<'tcx>,
val: LvalueRef<'tcx>,
skip_dtor: bool,
}

impl<'tcx> DropValue<'tcx> {
fn trans<'a>(&self, funclet: Option<&'a Funclet>, bcx: &Builder<'a, 'tcx>) {
glue::call_drop_glue(bcx, self.val, self.ty, self.skip_dtor, funclet)
glue::call_drop_glue(bcx, self.val, self.skip_dtor, funclet)
}

/// Creates a landing pad for the top scope. The landing pad will perform all cleanups necessary
@@ -96,12 +95,16 @@ impl<'tcx> DropValue<'tcx> {
impl<'a, 'tcx> CleanupScope<'tcx> {
/// Schedules a (deep) drop of `val`, which is a pointer to an instance of `ty`
pub fn schedule_drop_mem(
bcx: &Builder<'a, 'tcx>, val: MaybeSizedValue, ty: Ty<'tcx>
bcx: &Builder<'a, 'tcx>, val: LvalueRef<'tcx>
) -> CleanupScope<'tcx> {
if !bcx.ccx.shared().type_needs_drop(ty) { return CleanupScope::noop(); }
if let LvalueTy::Downcast { .. } = val.ty {
bug!("Cannot drop downcast ty yet");
}
if !bcx.ccx.shared().type_needs_drop(val.ty.to_ty(bcx.tcx())) {
return CleanupScope::noop();
}
let drop = DropValue {
val: val,
ty: ty,
skip_dtor: false,
};

@@ -114,15 +117,19 @@ impl<'a, 'tcx> CleanupScope<'tcx> {
/// and dropping the contents associated with that variant
/// *without* executing any associated drop implementation.
pub fn schedule_drop_adt_contents(
bcx: &Builder<'a, 'tcx>, val: MaybeSizedValue, ty: Ty<'tcx>
bcx: &Builder<'a, 'tcx>, val: LvalueRef<'tcx>
) -> CleanupScope<'tcx> {
if let LvalueTy::Downcast { .. } = val.ty {
bug!("Cannot drop downcast ty yet");
}
// `if` below could be "!contents_needs_drop"; skipping drop
// is just an optimization, so sound to be conservative.
if !bcx.ccx.shared().type_needs_drop(ty) { return CleanupScope::noop(); }
if !bcx.ccx.shared().type_needs_drop(val.ty.to_ty(bcx.tcx())) {
return CleanupScope::noop();
}

let drop = DropValue {
val: val,
ty: ty,
skip_dtor: true,
};

Loading