Skip to content

Commit 7e30ba8

Browse files
committed
librustc: Don't create scratch for the base expr in function record update.
1 parent f8e0ede commit 7e30ba8

File tree

1 file changed

+35
-30
lines changed

1 file changed

+35
-30
lines changed

src/librustc/middle/trans/expr.rs

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -746,12 +746,12 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
746746
controlflow::trans_block(bcx, &**blk, dest)
747747
}
748748
ast::ExprStruct(_, ref fields, base) => {
749-
trans_rec_or_struct(bcx,
750-
fields.as_slice(),
751-
base,
752-
expr.span,
753-
expr.id,
754-
dest)
749+
trans_struct(bcx,
750+
fields.as_slice(),
751+
base,
752+
expr.span,
753+
expr.id,
754+
dest)
755755
}
756756
ast::ExprTup(ref args) => {
757757
let repr = adt::represent_type(bcx.ccx(), expr_ty(bcx, expr));
@@ -1042,16 +1042,13 @@ pub fn with_field_tys<R>(tcx: &ty::ctxt,
10421042
}
10431043
}
10441044

1045-
fn trans_rec_or_struct<'a>(
1046-
bcx: &'a Block<'a>,
1047-
fields: &[ast::Field],
1048-
base: Option<Gc<ast::Expr>>,
1049-
expr_span: codemap::Span,
1050-
id: ast::NodeId,
1051-
dest: Dest)
1052-
-> &'a Block<'a> {
1045+
fn trans_struct<'a>(bcx: &'a Block<'a>,
1046+
fields: &[ast::Field],
1047+
base: Option<Gc<ast::Expr>>,
1048+
expr_span: codemap::Span,
1049+
id: ast::NodeId,
1050+
dest: Dest) -> &'a Block<'a> {
10531051
let _icx = push_ctxt("trans_rec");
1054-
let bcx = bcx;
10551052

10561053
let ty = node_id_type(bcx, id);
10571054
let tcx = bcx.tcx();
@@ -1121,15 +1118,14 @@ pub struct StructBaseInfo {
11211118
* - `optbase` contains information on the base struct (if any) from
11221119
* which remaining fields are copied; see comments on `StructBaseInfo`.
11231120
*/
1124-
pub fn trans_adt<'a>(bcx: &'a Block<'a>,
1121+
pub fn trans_adt<'a>(mut bcx: &'a Block<'a>,
11251122
repr: &adt::Repr,
11261123
discr: ty::Disr,
11271124
fields: &[(uint, Gc<ast::Expr>)],
11281125
optbase: Option<StructBaseInfo>,
11291126
dest: Dest) -> &'a Block<'a> {
11301127
let _icx = push_ctxt("trans_adt");
11311128
let fcx = bcx.fcx;
1132-
let mut bcx = bcx;
11331129
let addr = match dest {
11341130
Ignore => {
11351131
for &(_i, ref e) in fields.iter() {
@@ -1148,6 +1144,28 @@ pub fn trans_adt<'a>(bcx: &'a Block<'a>,
11481144
// failure occur before the ADT as a whole is ready.
11491145
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
11501146

1147+
// First we trans the base, if we have one, to the dest
1148+
for base in optbase.iter() {
1149+
assert_eq!(discr, 0);
1150+
1151+
match ty::expr_kind(bcx.tcx(), &*base.expr) {
1152+
ty::LvalueExpr => {
1153+
let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base"));
1154+
for &(i, t) in base.fields.iter() {
1155+
let datum = base_datum.get_element(
1156+
t, |srcval| adt::trans_field_ptr(bcx, repr, srcval, discr, i));
1157+
let dest = adt::trans_field_ptr(bcx, repr, addr, discr, i);
1158+
bcx = datum.store_to(bcx, dest);
1159+
}
1160+
},
1161+
ty::RvalueDpsExpr | ty::RvalueDatumExpr => {
1162+
bcx = trans_into(bcx, &*base.expr, SaveIn(addr));
1163+
},
1164+
ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr")
1165+
}
1166+
}
1167+
1168+
// Now, we just overwrite the fields we've explicity specified
11511169
for &(i, ref e) in fields.iter() {
11521170
let dest = adt::trans_field_ptr(bcx, repr, addr, discr, i);
11531171
let e_ty = expr_ty_adjusted(bcx, &**e);
@@ -1157,19 +1175,6 @@ pub fn trans_adt<'a>(bcx: &'a Block<'a>,
11571175
fcx.schedule_drop_mem(scope, dest, e_ty);
11581176
}
11591177

1160-
for base in optbase.iter() {
1161-
// FIXME #6573: is it sound to use the destination's repr on the base?
1162-
// And, would it ever be reasonable to be here with discr != 0?
1163-
let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base"));
1164-
for &(i, t) in base.fields.iter() {
1165-
let datum = base_datum.get_element(
1166-
t,
1167-
|srcval| adt::trans_field_ptr(bcx, repr, srcval, discr, i));
1168-
let dest = adt::trans_field_ptr(bcx, repr, addr, discr, i);
1169-
bcx = datum.store_to(bcx, dest);
1170-
}
1171-
}
1172-
11731178
adt::trans_set_discr(bcx, repr, addr, discr);
11741179

11751180
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);

0 commit comments

Comments
 (0)