Convert expr_struct to use adt, and try to share code with tuples.
This commit is contained in:
parent
5cbc2571c1
commit
fdd28451f6
1 changed files with 73 additions and 106 deletions
|
@ -604,7 +604,8 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
|
|||
}
|
||||
ast::expr_tup(ref args) => {
|
||||
let repr = adt::represent_type(bcx.ccx(), expr_ty(bcx, expr));
|
||||
return trans_adt(bcx, &repr, 0, *args, dest);
|
||||
return trans_adt(bcx, &repr, 0, args.mapi(|i, arg| (i, *arg)),
|
||||
None, dest);
|
||||
}
|
||||
ast::expr_lit(@codemap::spanned {node: ast::lit_str(s), _}) => {
|
||||
return tvec::trans_lit_str(bcx, expr, s, dest);
|
||||
|
@ -885,7 +886,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
|||
let _icx = bcx.insn_ctxt("trans_rec_field");
|
||||
|
||||
let base_datum = unpack_datum!(bcx, trans_to_datum(bcx, base));
|
||||
do with_field_tys(bcx.tcx(), base_datum.ty, None) |_dtor, field_tys| {
|
||||
do with_field_tys(bcx.tcx(), base_datum.ty, None) |_disr, field_tys| {
|
||||
let ix = ty::field_idx_strict(bcx.tcx(), field, field_tys);
|
||||
DatumBlock {
|
||||
datum: base_datum.GEPi(bcx,
|
||||
|
@ -1098,15 +1099,14 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
|
|||
pub fn with_field_tys<R>(tcx: ty::ctxt,
|
||||
ty: ty::t,
|
||||
node_id_opt: Option<ast::node_id>,
|
||||
op: fn(bool, (&[ty::field])) -> R) -> R {
|
||||
op: fn(int, (&[ty::field])) -> R) -> R {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_rec(ref fields) => {
|
||||
op(false, *fields)
|
||||
op(0, *fields)
|
||||
}
|
||||
|
||||
ty::ty_struct(did, ref substs) => {
|
||||
let has_dtor = ty::ty_dtor(tcx, did).is_present();
|
||||
op(has_dtor, struct_mutable_fields(tcx, did, substs))
|
||||
op(0, struct_mutable_fields(tcx, did, substs))
|
||||
}
|
||||
|
||||
ty::ty_enum(_, ref substs) => {
|
||||
|
@ -1120,8 +1120,10 @@ pub fn with_field_tys<R>(tcx: ty::ctxt,
|
|||
}
|
||||
Some(node_id) => {
|
||||
match tcx.def_map.get(&node_id) {
|
||||
ast::def_variant(_, variant_id) => {
|
||||
op(false, struct_mutable_fields(
|
||||
ast::def_variant(enum_id, variant_id) => {
|
||||
let variant_info = ty::enum_variant_with_id(
|
||||
tcx, enum_id, variant_id);
|
||||
op(variant_info.disr_val, struct_mutable_fields(
|
||||
tcx, variant_id, substs))
|
||||
}
|
||||
_ => {
|
||||
|
@ -1150,135 +1152,100 @@ fn trans_rec_or_struct(bcx: block,
|
|||
let _icx = bcx.insn_ctxt("trans_rec");
|
||||
let mut bcx = bcx;
|
||||
|
||||
// Handle the case where the result is ignored.
|
||||
let addr;
|
||||
match dest {
|
||||
SaveIn(p) => {
|
||||
addr = p;
|
||||
}
|
||||
Ignore => {
|
||||
// just evaluate the values for each field and drop them
|
||||
// on the floor
|
||||
for vec::each(fields) |fld| {
|
||||
bcx = trans_into(bcx, fld.node.expr, Ignore);
|
||||
}
|
||||
return bcx;
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a struct-like variant, write in the discriminant if
|
||||
// necessary, position the address at the right location, and cast the
|
||||
// address.
|
||||
let ty = node_id_type(bcx, id);
|
||||
let tcx = bcx.tcx();
|
||||
let addr = match ty::get(ty).sty {
|
||||
ty::ty_enum(_, ref substs) => {
|
||||
match tcx.def_map.get(&id) {
|
||||
ast::def_variant(enum_id, variant_id) => {
|
||||
let variant_info = ty::enum_variant_with_id(
|
||||
tcx, enum_id, variant_id);
|
||||
let addr = if ty::enum_is_univariant(tcx, enum_id) {
|
||||
addr
|
||||
} else {
|
||||
Store(bcx,
|
||||
C_int(bcx.ccx(), variant_info.disr_val),
|
||||
GEPi(bcx, addr, [0, 0]));
|
||||
GEPi(bcx, addr, [0, 1])
|
||||
};
|
||||
let fields = ty::struct_mutable_fields(
|
||||
tcx, variant_id, substs);
|
||||
let field_lltys = do fields.map |field| {
|
||||
type_of::type_of(bcx.ccx(),
|
||||
ty::subst_tps(
|
||||
tcx, substs.tps, None, field.mt.ty))
|
||||
};
|
||||
PointerCast(bcx, addr,
|
||||
T_ptr(T_struct(~[T_struct(field_lltys)])))
|
||||
do with_field_tys(tcx, ty, Some(id)) |discr, field_tys| {
|
||||
let mut need_base = vec::from_elem(field_tys.len(), true);
|
||||
|
||||
let numbered_fields = do fields.map |field| {
|
||||
match do vec::position(field_tys) |field_ty| {
|
||||
field_ty.ident == field.node.ident
|
||||
} {
|
||||
Some(i) => {
|
||||
need_base[i] = false;
|
||||
(i, field.node.expr)
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.bug(~"resolve didn't write the right def in for \
|
||||
this struct-like variant")
|
||||
None => {
|
||||
tcx.sess.span_bug(field.span,
|
||||
~"Couldn't find field in struct type")
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => addr
|
||||
};
|
||||
|
||||
do with_field_tys(tcx, ty, Some(id)) |has_dtor, field_tys| {
|
||||
// evaluate each of the fields and store them into their
|
||||
// correct locations
|
||||
let mut temp_cleanups = ~[];
|
||||
for fields.each |field| {
|
||||
let ix = ty::field_idx_strict(tcx, field.node.ident, field_tys);
|
||||
let dest = GEPi(bcx, addr, struct_field(ix));
|
||||
bcx = trans_into(bcx, field.node.expr, SaveIn(dest));
|
||||
add_clean_temp_mem(bcx, dest, field_tys[ix].mt.ty);
|
||||
temp_cleanups.push(dest);
|
||||
}
|
||||
|
||||
// copy over any remaining fields from the base (for
|
||||
// functional record update)
|
||||
for base.each |base_expr| {
|
||||
let base_datum = unpack_datum!(
|
||||
bcx, trans_to_datum(bcx, *base_expr));
|
||||
|
||||
// Copy/move over inherited fields
|
||||
for field_tys.eachi |i, field_ty| {
|
||||
if !fields.any(|f| f.node.ident == field_ty.ident) {
|
||||
let dest = GEPi(bcx, addr, struct_field(i));
|
||||
let base_field =
|
||||
base_datum.GEPi(bcx,
|
||||
struct_field(i),
|
||||
field_ty.mt.ty,
|
||||
ZeroMem);
|
||||
bcx = base_field.store_to(bcx, base_expr.id, INIT, dest);
|
||||
};
|
||||
let optbase = match base {
|
||||
Some(base_expr) => {
|
||||
let mut leftovers = ~[];
|
||||
for need_base.eachi |i, b| {
|
||||
if *b {
|
||||
leftovers.push((i, field_tys[i].mt.ty))
|
||||
}
|
||||
}
|
||||
Some(StructBaseInfo {expr: base_expr,
|
||||
fields: leftovers })
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if need_base.any(|b| *b) {
|
||||
// XXX should be span bug
|
||||
tcx.sess.bug(~"missing fields and no base expr")
|
||||
}
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
// Add the drop flag if necessary.
|
||||
if has_dtor {
|
||||
let dest = GEPi(bcx, addr, struct_dtor());
|
||||
Store(bcx, C_u8(1), dest);
|
||||
}
|
||||
|
||||
// Now revoke the cleanups as we pass responsibility for the data
|
||||
// structure on to the caller
|
||||
for temp_cleanups.each |cleanup| {
|
||||
revoke_clean(bcx, *cleanup);
|
||||
}
|
||||
bcx
|
||||
let repr = adt::represent_type(bcx.ccx(), ty);
|
||||
trans_adt(bcx, &repr, discr, numbered_fields, optbase, dest)
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_adt(bcx: block, repr: &adt::Repr, discr: int, elts: &[@ast::expr],
|
||||
struct StructBaseInfo {
|
||||
expr: @ast::expr,
|
||||
fields: ~[(uint, ty::t)]
|
||||
}
|
||||
|
||||
fn trans_adt(bcx: block, repr: &adt::Repr, discr: int,
|
||||
fields: &[(uint, @ast::expr)],
|
||||
optbase: Option<StructBaseInfo>,
|
||||
dest: Dest) -> block {
|
||||
let _icx = bcx.insn_ctxt("trans_tup");
|
||||
let _icx = bcx.insn_ctxt("trans_adt");
|
||||
let mut bcx = bcx;
|
||||
let addr = match dest {
|
||||
Ignore => {
|
||||
for vec::each(elts) |ex| {
|
||||
bcx = trans_into(bcx, *ex, Ignore);
|
||||
for fields.each |&(_i, e)| {
|
||||
bcx = trans_into(bcx, e, Ignore);
|
||||
}
|
||||
for optbase.each |sbi| {
|
||||
bcx = trans_into(bcx, sbi.expr, Ignore);
|
||||
}
|
||||
return bcx;
|
||||
}
|
||||
SaveIn(pos) => pos,
|
||||
SaveIn(pos) => pos
|
||||
};
|
||||
let mut temp_cleanups = ~[];
|
||||
adt::trans_set_discr(bcx, repr, addr, discr);
|
||||
for vec::eachi(elts) |i, e| {
|
||||
for fields.each |&(i, e)| {
|
||||
let dest = adt::trans_GEP(bcx, repr, addr, discr, i);
|
||||
let e_ty = expr_ty(bcx, *e);
|
||||
bcx = trans_into(bcx, *e, SaveIn(dest));
|
||||
let e_ty = expr_ty(bcx, e);
|
||||
bcx = trans_into(bcx, e, SaveIn(dest));
|
||||
add_clean_temp_mem(bcx, dest, e_ty);
|
||||
temp_cleanups.push(dest);
|
||||
}
|
||||
for optbase.each |base| {
|
||||
let base_datum = unpack_datum!(bcx, trans_to_datum(bcx, base.expr));
|
||||
for base.fields.each |&(i, t)| {
|
||||
let datum =
|
||||
// XXX convert this to adt
|
||||
base_datum.GEPi(bcx, struct_field(i), t, ZeroMem);
|
||||
let dest = adt::trans_GEP(bcx, repr, addr, discr, i);
|
||||
bcx = datum.store_to(bcx, base.expr.id, INIT, dest);
|
||||
}
|
||||
}
|
||||
|
||||
for vec::each(temp_cleanups) |cleanup| {
|
||||
revoke_clean(bcx, *cleanup);
|
||||
}
|
||||
return bcx;
|
||||
}
|
||||
|
||||
|
||||
fn trans_immediate_lit(bcx: block, expr: @ast::expr,
|
||||
lit: ast::lit) -> DatumBlock {
|
||||
// must not be a string constant, that is a RvalueDpsExpr
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue