Skip to content

Removing RefCells and Cells from FunctionContext in trans #25332

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

Closed
wants to merge 11 commits into from
Closed
501 changes: 266 additions & 235 deletions src/librustc_trans/trans/_match.rs

Large diffs are not rendered by default.

113 changes: 62 additions & 51 deletions src/librustc_trans/trans/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ pub struct Struct<'tcx> {
/// Convenience for `represent_type`. There should probably be more or
/// these, for places in trans where the `Ty` isn't directly
/// available.
pub fn represent_node<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
node: ast::NodeId) -> Rc<Repr<'tcx>> {
pub fn represent_node<'r, 'blk, 'tcx>(bcx: &mut Block<'r, 'blk, 'tcx>,
node: ast::NodeId) -> Rc<Repr<'tcx>> {
represent_type(bcx.ccx(), node_id_type(bcx, node))
}

Expand Down Expand Up @@ -778,9 +778,9 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
/// destructuring; this may or may not involve the actual discriminant.
///
/// This should ideally be less tightly tied to `_match`.
pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
r: &Repr<'tcx>, scrutinee: ValueRef)
-> (_match::BranchKind, Option<ValueRef>) {
pub fn trans_switch<'r, 'blk, 'tcx>(bcx: &mut Block<'r, 'blk, 'tcx>,
r: &Repr<'tcx>, scrutinee: ValueRef)
-> (_match::BranchKind, Option<ValueRef>) {
match *r {
CEnum(..) | General(..) |
RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
Expand All @@ -796,8 +796,8 @@ pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,


/// Obtain the actual discriminant of a value.
pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
scrutinee: ValueRef, cast_to: Option<Type>)
pub fn trans_get_discr<'r, 'blk, 'tcx>(bcx: &mut Block<'r, 'blk, 'tcx>, r: &Repr<'tcx>,
scrutinee: ValueRef, cast_to: Option<Type>)
-> ValueRef {
let signed;
let val;
Expand All @@ -819,7 +819,8 @@ pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
RawNullablePointer { nndiscr, nnty, .. } => {
let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
let llptrty = type_of::sizing_type_of(bcx.ccx(), nnty);
val = ICmp(bcx, cmp, Load(bcx, scrutinee), C_null(llptrty), DebugLoc::None);
let op = Load(bcx, scrutinee);
val = ICmp(bcx, cmp, op, C_null(llptrty), DebugLoc::None);
signed = false;
}
StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
Expand All @@ -833,7 +834,7 @@ pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
}
}

fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, discrfield: &DiscrField,
fn struct_wrapped_nullable_bitdiscr(bcx: &mut Block, nndiscr: Disr, discrfield: &DiscrField,
scrutinee: ValueRef) -> ValueRef {
let llptrptr = GEPi(bcx, scrutinee, &discrfield[..]);
let llptr = Load(bcx, llptrptr);
Expand All @@ -842,7 +843,7 @@ fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, discrfield: &Disc
}

/// Helper for cases where the discriminant is simply loaded.
fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
fn load_discr(bcx: &mut Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
-> ValueRef {
let llty = ll_inttype(bcx.ccx(), ity);
assert_eq!(val_ty(ptr), llty.ptr_to());
Expand All @@ -869,52 +870,56 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
/// discriminant-like value returned by `trans_switch`.
///
/// This should ideally be less tightly tied to `_match`.
pub fn trans_case<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr, discr: Disr)
-> _match::OptResult<'blk, 'tcx> {
pub fn trans_case<'r, 'blk, 'tcx>(bcx: &mut Block<'r, 'blk, 'tcx>, r: &Repr, discr: Disr)
-> _match::OptResult<'blk> {
match *r {
CEnum(ity, _, _) => {
_match::SingleResult(Result::new(bcx, C_integral(ll_inttype(bcx.ccx(), ity),
discr as u64, true)))
_match::SingleResult(Result::new(bcx.bl, C_integral(ll_inttype(bcx.ccx(), ity),
discr as u64, true)))
}
General(ity, _, _) => {
_match::SingleResult(Result::new(bcx, C_integral(ll_inttype(bcx.ccx(), ity),
discr as u64, true)))
_match::SingleResult(Result::new(bcx.bl, C_integral(ll_inttype(bcx.ccx(), ity),
discr as u64, true)))
}
Univariant(..) => {
bcx.ccx().sess().bug("no cases for univariants or structs")
}
RawNullablePointer { .. } |
StructWrappedNullablePointer { .. } => {
assert!(discr == 0 || discr == 1);
_match::SingleResult(Result::new(bcx, C_bool(bcx.ccx(), discr != 0)))
_match::SingleResult(Result::new(bcx.bl, C_bool(bcx.ccx(), discr != 0)))
}
}
}

/// Set the discriminant for a new value of the given case of the given
/// representation.
pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
val: ValueRef, discr: Disr) {
pub fn trans_set_discr<'r, 'blk, 'tcx>(bcx: &mut Block<'r, 'blk, 'tcx>, r: &Repr<'tcx>,
val: ValueRef, discr: Disr) {
match *r {
CEnum(ity, min, max) => {
assert_discr_in_range(ity, min, max, discr);
Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true),
let ty = ll_inttype(bcx.ccx(), ity);
Store(bcx, C_integral(ty, discr as u64, true),
val);
}
General(ity, ref cases, dtor) => {
if dtor_active(dtor) {
let ptr = trans_field_ptr(bcx, r, val, discr,
cases[discr as usize].fields.len() - 2);
Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED as usize), ptr);
let v = C_u8(bcx.ccx(), DTOR_NEEDED as usize);
Store(bcx, v, ptr);
}
Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true),
GEPi(bcx, val, &[0, 0]));
let ty = ll_inttype(bcx.ccx(), ity);
let p = GEPi(bcx, val, &[0, 0]);
Store(bcx, C_integral(ty, discr as u64, true), p);
}
Univariant(ref st, dtor) => {
assert_eq!(discr, 0);
if dtor_active(dtor) {
Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED as usize),
GEPi(bcx, val, &[0, st.fields.len() - 1]));
let v = C_u8(bcx.ccx(), DTOR_NEEDED as usize);
let p = GEPi(bcx, val, &[0, st.fields.len() - 1]);
Store(bcx, v, p);
}
}
RawNullablePointer { nndiscr, nnty, ..} => {
Expand Down Expand Up @@ -963,8 +968,8 @@ pub fn num_args(r: &Repr, discr: Disr) -> usize {
}

/// Access a field, at a point when the value's case is known.
pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
val: ValueRef, discr: Disr, ix: usize) -> ValueRef {
pub fn trans_field_ptr<'r, 'blk, 'tcx>(bcx: &mut Block<'r, 'blk, 'tcx>, r: &Repr<'tcx>,
val: ValueRef, discr: Disr, ix: usize) -> ValueRef {
// Note: if this ever needs to generate conditionals (e.g., if we
// decide to do some kind of cdr-coding-like non-unique repr
// someday), it will need to return a possibly-new bcx as well.
Expand Down Expand Up @@ -1002,8 +1007,9 @@ pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
}
}

pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, val: ValueRef,
ix: usize, needs_cast: bool) -> ValueRef {
pub fn struct_field_ptr<'r, 'blk, 'tcx>
(bcx: &mut Block<'r, 'blk, 'tcx>, st: &Struct<'tcx>, val: ValueRef,
ix: usize, needs_cast: bool) -> ValueRef {
let val = if needs_cast {
let ccx = bcx.ccx();
let fields = st.fields.iter().map(|&ty| type_of::type_of(ccx, ty)).collect::<Vec<_>>();
Expand All @@ -1016,29 +1022,29 @@ pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, v
GEPi(bcx, val, &[0, ix])
}

pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
r: &Repr<'tcx>,
value: ValueRef,
mut f: F)
-> Block<'blk, 'tcx> where
F: FnMut(Block<'blk, 'tcx>, &Struct<'tcx>, ValueRef) -> Block<'blk, 'tcx>,
pub fn fold_variants<'r, 'blk, 'tcx, F>
(bcx: &mut Block<'r, 'blk, 'tcx>,
r: &Repr<'tcx>,
value: ValueRef,
mut f: F)
-> &'blk BlockS where
F: for<'a> FnMut(&mut Block<'a, 'blk, 'tcx>, &Struct<'tcx>, ValueRef) -> &'blk BlockS,
{
let fcx = bcx.fcx;
match *r {
Univariant(ref st, _) => {
f(bcx, st, value)
}
General(ity, ref cases, _) => {
let ccx = bcx.ccx();
let unr_cx = fcx.new_temp_block("enum-variant-iter-unr");
Unreachable(unr_cx);
let unr_cx = bcx.fcx.new_temp_block("enum-variant-iter-unr");
Unreachable(&mut unr_cx.with(bcx.fcx));

let discr_val = trans_get_discr(bcx, r, value, None);
let llswitch = Switch(bcx, discr_val, unr_cx.llbb, cases.len());
let bcx_next = fcx.new_temp_block("enum-variant-iter-next");
let bcx_next = bcx.fcx.new_temp_block("enum-variant-iter-next");

for (discr, case) in cases.iter().enumerate() {
let mut variant_cx = fcx.new_temp_block(
let variant_cx = bcx.fcx.new_temp_block(
&format!("enum-variant-iter-{}", &discr.to_string())
);
let rhs_val = C_integral(ll_inttype(ccx, ity), discr as u64, true);
Expand All @@ -1047,10 +1053,12 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
let fields = case.fields.iter().map(|&ty|
type_of::type_of(bcx.ccx(), ty)).collect::<Vec<_>>();
let real_ty = Type::struct_(ccx, &fields[..], case.packed);
let variant_value = PointerCast(variant_cx, value, real_ty.ptr_to());
let variant_value = PointerCast(&mut variant_cx.with(bcx.fcx),
value, real_ty.ptr_to());

variant_cx = f(variant_cx, case, variant_value);
Br(variant_cx, bcx_next.llbb, DebugLoc::None);
let mut bcx = &mut variant_cx.with(bcx.fcx);
let variant_cx = f(bcx, case, variant_value);
Br(&mut variant_cx.with(bcx.fcx), bcx_next.llbb, DebugLoc::None);
}

bcx_next
Expand All @@ -1060,9 +1068,13 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
}

/// Access the struct drop flag, if present.
pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, val: ValueRef)
-> datum::DatumBlock<'blk, 'tcx, datum::Expr>
pub fn trans_drop_flag_ptr<'r, 'blk, 'tcx>
(&mut Block { bl, ref mut fcx }: &mut Block<'r, 'blk, 'tcx>,
r: &Repr<'tcx>, val: ValueRef)
-> datum::DatumBlock<'blk, 'tcx, datum::Expr>
{
//let Block { bl, ref mut fcx } = *bcx;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, yes. Good catch!

let mut bcx = &mut bl.with(fcx);
let tcx = bcx.tcx();
let ptr_ty = ty::mk_imm_ptr(bcx.tcx(), tcx.dtor_type());
match *r {
Expand All @@ -1071,20 +1083,19 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx
datum::immediate_rvalue_bcx(bcx, flag_ptr, ptr_ty).to_expr_datumblock()
}
General(_, _, dtor) if dtor_active(dtor) => {
let fcx = bcx.fcx;
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
let custom_cleanup_scope = bcx.fcx.push_custom_cleanup_scope();
let scratch = unpack_datum!(bcx, datum::lvalue_scratch_datum(
bcx, tcx.dtor_type(), "drop_flag",
cleanup::CustomScope(custom_cleanup_scope), (), |_, bcx, _| bcx
cleanup::CustomScope(custom_cleanup_scope), (), |_, bcx, _| bcx.bl
));
bcx = fold_variants(bcx, r, val, |variant_cx, st, value| {
let bl = fold_variants(bcx, r, val, |variant_cx, st, value| {
let ptr = struct_field_ptr(variant_cx, st, value, (st.fields.len() - 1), false);
datum::Datum::new(ptr, ptr_ty, datum::Lvalue)
.store_to(variant_cx, scratch.val)
});
let expr_datum = scratch.to_expr_datum();
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
datum::DatumBlock::new(bcx, expr_datum)
bcx.fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
datum::DatumBlock::new(bl, expr_datum)
}
_ => bcx.ccx().sess().bug("tried to get drop flag of non-droppable type")
}
Expand Down
44 changes: 24 additions & 20 deletions src/librustc_trans/trans/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,56 +25,61 @@ use std::ffi::CString;
use libc::{c_uint, c_char};

// Take an inline assembly expression and splat it out via LLVM
pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
-> Block<'blk, 'tcx> {
let fcx = bcx.fcx;
let mut bcx = bcx;
pub fn trans_inline_asm<'r, 'blk, 'tcx>(&mut Block { bl, ref mut fcx }: &mut Block<'r, 'blk, 'tcx>,
ia: &ast::InlineAsm)
-> &'blk BlockS {
let mut bcx = &mut bl.with(fcx);
let mut constraints = Vec::new();
let mut output_types = Vec::new();

let temp_scope = fcx.push_custom_cleanup_scope();
let temp_scope = bcx.fcx.push_custom_cleanup_scope();

let mut ext_inputs = Vec::new();
let mut ext_constraints = Vec::new();

// Prepare the output operands
let outputs = ia.outputs.iter().enumerate().map(|(i, &(ref c, ref out, is_rw))| {
let mut outputs = Vec::new();

for (i, &(ref c, ref out, is_rw)) in ia.outputs.iter().enumerate() {
constraints.push((*c).clone());

let out_datum = unpack_datum!(bcx, expr::trans(bcx, &**out));
output_types.push(type_of::type_of(bcx.ccx(), out_datum.ty));
let val = out_datum.val;
if is_rw {
ext_inputs.push(unpack_result!(bcx, {
let expr_ty = expr_ty(bcx, &**out);
callee::trans_arg_datum(bcx,
expr_ty(bcx, &**out),
out_datum,
cleanup::CustomScope(temp_scope),
callee::DontAutorefArg)
expr_ty,
out_datum,
cleanup::CustomScope(temp_scope),
callee::DontAutorefArg)
}));
ext_constraints.push(i.to_string());
}
val
outputs.push(val);

}).collect::<Vec<_>>();
}

// Now the input operands
let mut inputs = ia.inputs.iter().map(|&(ref c, ref input)| {
let mut inputs = Vec::new();
for &(ref c, ref input) in &ia.inputs {
constraints.push((*c).clone());

let in_datum = unpack_datum!(bcx, expr::trans(bcx, &**input));
unpack_result!(bcx, {
inputs.push(unpack_result!(bcx, {
let expr_ty = expr_ty(bcx, &**input);
callee::trans_arg_datum(bcx,
expr_ty(bcx, &**input),
expr_ty,
in_datum,
cleanup::CustomScope(temp_scope),
callee::DontAutorefArg)
})
}).collect::<Vec<_>>();
}));
}
inputs.push_all(&ext_inputs[..]);

// no failure occurred preparing operands, no need to cleanup
fcx.pop_custom_cleanup_scope(temp_scope);
bcx.fcx.pop_custom_cleanup_scope(temp_scope);

let clobbers = ia.clobbers.iter()
.map(|s| format!("~{{{}}}", &s));
Expand Down Expand Up @@ -144,7 +149,6 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
llvm::LLVMMDNodeInContext(bcx.ccx().llcx(), &val, 1));
}

return bcx;

return bcx.bl;
}

Loading