Skip to content

Commit 32e8429

Browse files
committed
rustc: Translate struct literals
1 parent b91da09 commit 32e8429

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

src/rustc/middle/trans/base.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3410,6 +3410,90 @@ fn trans_rec(bcx: block, fields: ~[ast::field],
34103410
ret bcx;
34113411
}
34123412

3413+
fn trans_struct(block_context: block, span: span, fields: ~[ast::field],
3414+
id: ast::node_id, dest: dest) -> block {
3415+
3416+
let _instruction_context = block_context.insn_ctxt(~"trans_struct");
3417+
let mut block_context = block_context;
3418+
let type_context = block_context.ccx().tcx;
3419+
3420+
let struct_type = node_id_type(block_context, id);
3421+
3422+
// Get the address to store the structure into. If there is no address,
3423+
// just translate each field and be done with it.
3424+
let dest_address;
3425+
alt dest {
3426+
ignore => {
3427+
for fields.each |field| {
3428+
block_context = trans_expr(block_context,
3429+
field.node.expr,
3430+
ignore);
3431+
}
3432+
ret block_context;
3433+
}
3434+
save_in(destination_address) => {
3435+
dest_address = destination_address;
3436+
}
3437+
by_val(_) => {
3438+
type_context.sess.span_bug(span, ~"didn't expect by_val");
3439+
}
3440+
}
3441+
3442+
// Get the class ID and its fields.
3443+
let class_fields, class_id, substitutions;
3444+
alt ty::get(struct_type).struct {
3445+
ty::ty_class(existing_class_id, existing_substitutions) => {
3446+
class_id = existing_class_id;
3447+
substitutions = existing_substitutions;
3448+
class_fields = ty::lookup_class_fields(type_context, class_id);
3449+
}
3450+
_ => {
3451+
type_context.sess.span_bug(span, ~"didn't resolve to a struct");
3452+
}
3453+
}
3454+
3455+
// Now translate each field.
3456+
let mut temp_cleanups = ~[];
3457+
for fields.each |field| {
3458+
let mut found = none;
3459+
for class_fields.eachi |i, class_field| {
3460+
if str::eq(*class_field.ident, *field.node.ident) {
3461+
found = some((i, class_field.id));
3462+
break;
3463+
}
3464+
}
3465+
3466+
let index, field_id;
3467+
alt found {
3468+
some((found_index, found_field_id)) => {
3469+
index = found_index;
3470+
field_id = found_field_id;
3471+
}
3472+
none => {
3473+
type_context.sess.span_bug(span, ~"unknown field");
3474+
}
3475+
}
3476+
3477+
let dest = GEPi(block_context, dest_address, ~[0, index]);
3478+
block_context = trans_expr_save_in(block_context,
3479+
field.node.expr,
3480+
dest);
3481+
3482+
let field_type = ty::lookup_field_type(type_context, class_id,
3483+
field_id, substitutions);
3484+
add_clean_temp_mem(block_context, dest, field_type);
3485+
vec::push(temp_cleanups, dest);
3486+
}
3487+
3488+
// Now revoke the cleanups, as we pass responsibility for the data
3489+
// structure onto the caller.
3490+
for temp_cleanups.each |temp_cleanup| {
3491+
revoke_clean(block_context, temp_cleanup);
3492+
}
3493+
3494+
block_context
3495+
}
3496+
34133497
// Store the result of an expression in the given memory location, ensuring
34143498
// that nil or bot expressions get ignore rather than save_in as destination.
34153499
fn trans_expr_save_in(bcx: block, e: @ast::expr, dest: ValueRef)
@@ -3558,6 +3642,9 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
35583642
ast::expr_rec(args, base) {
35593643
ret trans_rec(bcx, args, base, e.id, dest);
35603644
}
3645+
ast::expr_struct(_, fields) {
3646+
ret trans_struct(bcx, e.span, fields, e.id, dest);
3647+
}
35613648
ast::expr_tup(args) { ret trans_tup(bcx, args, dest); }
35623649
ast::expr_vstore(e, v) { ret tvec::trans_vstore(bcx, e, v, dest); }
35633650
ast::expr_lit(lit) { ret trans_lit(bcx, e, *lit, dest); }

0 commit comments

Comments
 (0)