Skip to content

Commit 51a5a4a

Browse files
committed
rustc: Translate repeated vector syntax
1 parent 488ece0 commit 51a5a4a

File tree

5 files changed

+106
-45
lines changed

5 files changed

+106
-45
lines changed

src/rustc/middle/trans/base.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -3636,8 +3636,13 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
36363636
}
36373637
ast::expr_lit(lit) { return trans_lit(bcx, e, *lit, dest); }
36383638
ast::expr_vec(args, _) {
3639-
return tvec::trans_evec(bcx, args, ast::vstore_fixed(none),
3640-
e.id, dest);
3639+
return tvec::trans_evec(bcx, tvec::individual_evec(args),
3640+
ast::vstore_fixed(none), e.id, dest);
3641+
}
3642+
ast::expr_repeat(element, count_expr, _) {
3643+
let count = ty::eval_repeat_count(bcx.tcx(), count_expr, e.span);
3644+
return tvec::trans_evec(bcx, tvec::repeating_evec(element, count),
3645+
ast::vstore_fixed(none), e.id, dest);
36413646
}
36423647
ast::expr_binary(op, lhs, rhs) {
36433648
return trans_binary(bcx, op, lhs, rhs, dest, e);

src/rustc/middle/trans/tvec.rs

+69-21
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import back::abi;
55
import base::{call_memmove,
66
INIT, copy_val, load_if_immediate, get_tydesc,
77
sub_block, do_spill_noroot,
8-
dest, bcx_icx, non_gc_box_cast};
8+
dest, bcx_icx, non_gc_box_cast, move_val, lval_owned};
99
import syntax::codemap::span;
1010
import shape::llsize_of;
1111
import build::*;
@@ -118,18 +118,39 @@ fn make_drop_glue_unboxed(bcx: block, vptr: ValueRef, vec_ty: ty::t) ->
118118
} else { bcx }
119119
}
120120

121-
fn trans_evec(bcx: block, args: ~[@ast::expr],
121+
enum evec_elements {
122+
individual_evec(~[@ast::expr]),
123+
repeating_evec(@ast::expr, uint)
124+
}
125+
126+
fn trans_evec(bcx: block, elements: evec_elements,
122127
vst: ast::vstore, id: ast::node_id, dest: dest) -> block {
123128
let _icx = bcx.insn_ctxt(~"tvec::trans_evec");
124129
let ccx = bcx.ccx();
125130
let mut bcx = bcx;
131+
132+
// Handle the ignored case.
126133
if dest == base::ignore {
127-
for vec::each(args) |arg| {
128-
bcx = base::trans_expr(bcx, arg, base::ignore);
134+
match elements {
135+
individual_evec(args) => {
136+
for vec::each(args) |arg| {
137+
bcx = base::trans_expr(bcx, arg, base::ignore);
138+
}
139+
}
140+
repeating_evec(element, _) => {
141+
bcx = base::trans_expr(bcx, element, base::ignore);
142+
}
129143
}
130144
return bcx;
131145
}
132146

147+
// Figure out the number of elements we need.
148+
let count;
149+
match elements {
150+
individual_evec(args) => count = args.len(),
151+
repeating_evec(_, len) => count = len
152+
}
153+
133154
let vec_ty = node_id_type(bcx, id);
134155
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
135156
let llunitty = type_of::type_of(ccx, unit_ty);
@@ -151,13 +172,12 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
151172
{bcx: bcx, val: v, dataptr: v}
152173
}
153174
ast::vstore_slice(_) {
154-
let n = vec::len(args);
155175
// Make a fake type to use for the cleanup
156176
let ty = ty::mk_evec(bcx.tcx(),
157177
{ty: unit_ty, mutbl: ast::m_mutbl},
158-
ty::vstore_fixed(n));
178+
ty::vstore_fixed(count));
159179

160-
let n = C_uint(ccx, n);
180+
let n = C_uint(ccx, count);
161181
let vp = base::arrayalloca(bcx, llunitty, n);
162182
add_clean(bcx, vp, ty);
163183

@@ -171,15 +191,13 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
171191
{bcx: bcx, val: p, dataptr: vp}
172192
}
173193
ast::vstore_uniq {
174-
let {bcx, val} = alloc_vec(bcx, unit_ty, args.len(),
175-
heap_exchange);
194+
let {bcx, val} = alloc_vec(bcx, unit_ty, count, heap_exchange);
176195
add_clean_free(bcx, val, heap_exchange);
177196
let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val));
178197
{bcx: bcx, val: val, dataptr: dataptr}
179198
}
180199
ast::vstore_box {
181-
let {bcx, val} = alloc_vec(bcx, unit_ty, args.len(),
182-
heap_shared);
200+
let {bcx, val} = alloc_vec(bcx, unit_ty, count, heap_shared);
183201
add_clean_free(bcx, val, heap_shared);
184202
let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val));
185203
{bcx: bcx, val: val, dataptr: dataptr}
@@ -192,12 +210,38 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
192210
debug!{"trans_evec: v: %s, dataptr: %s",
193211
val_str(ccx.tn, val),
194212
val_str(ccx.tn, dataptr)};
195-
for vec::each(args) |e| {
196-
let lleltptr = InBoundsGEP(bcx, dataptr, ~[C_uint(ccx, i)]);
197-
bcx = base::trans_expr_save_in(bcx, e, lleltptr);
198-
add_clean_temp_mem(bcx, lleltptr, unit_ty);
199-
vec::push(temp_cleanups, lleltptr);
200-
i += 1u;
213+
match elements {
214+
individual_evec(args) => {
215+
for vec::each(args) |e| {
216+
let lleltptr = InBoundsGEP(bcx, dataptr, ~[C_uint(ccx, i)]);
217+
bcx = base::trans_expr_save_in(bcx, e, lleltptr);
218+
add_clean_temp_mem(bcx, lleltptr, unit_ty);
219+
vec::push(temp_cleanups, lleltptr);
220+
i += 1u;
221+
}
222+
}
223+
repeating_evec(e, len) => {
224+
// We make temporary space in the hope that this will be
225+
// friendlier to LLVM alias analysis.
226+
let lltmpspace = base::alloca(bcx, llunitty);
227+
bcx = base::trans_expr_save_in(bcx, e, lltmpspace);
228+
add_clean_temp_mem(bcx, lltmpspace, unit_ty);
229+
vec::push(temp_cleanups, lltmpspace);
230+
for len.timesi |i| {
231+
let lleltptr = InBoundsGEP(bcx, dataptr, ~[C_uint(ccx, i)]);
232+
if i == len - 1 {
233+
// Move the last one in.
234+
bcx = move_val(bcx, INIT, lleltptr,
235+
lval_owned(bcx, lltmpspace), unit_ty);
236+
} else {
237+
// Copy all but the last one in.
238+
let llval = load_if_immediate(bcx, lltmpspace, unit_ty);
239+
bcx = copy_val(bcx, INIT, lleltptr, llval, unit_ty);
240+
}
241+
add_clean_temp_mem(bcx, lleltptr, unit_ty);
242+
vec::push(temp_cleanups, lleltptr);
243+
}
244+
}
201245
}
202246

203247
for vec::each(temp_cleanups) |cln| { revoke_clean(bcx, cln); }
@@ -219,13 +263,17 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
219263
fn trans_vstore(bcx: block, e: @ast::expr,
220264
v: ast::vstore, dest: dest) -> block {
221265
alt e.node {
222-
ast::expr_lit(@{node: ast::lit_str(s), span: _}) {
266+
ast::expr_lit(@{node: ast::lit_str(s), span: _}) => {
223267
return trans_estr(bcx, s, some(v), dest);
224268
}
225-
ast::expr_vec(es, mutbl) {
226-
return trans_evec(bcx, es, v, e.id, dest);
269+
ast::expr_vec(es, mutbl) => {
270+
return trans_evec(bcx, individual_evec(es), v, e.id, dest);
227271
}
228-
_ {
272+
ast::expr_repeat(element, count_expr, mutbl) => {
273+
let count = ty::eval_repeat_count(bcx.tcx(), count_expr, e.span);
274+
return trans_evec(bcx, repeating_evec(element, count), v, e.id, dest);
275+
}
276+
_ => {
229277
bcx.sess().span_bug(e.span, ~"vstore on non-sequence type");
230278
}
231279
}

src/rustc/middle/ty.rs

+21
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ export terr_proto_mismatch;
169169
export terr_ret_style_mismatch;
170170
export purity_to_str;
171171
export param_tys_in_type;
172+
export eval_repeat_count;
172173

173174
// Data types
174175

@@ -3170,6 +3171,26 @@ fn normalize_ty(cx: ctxt, t: t) -> t {
31703171
return t_norm;
31713172
}
31723173

3174+
// Returns the repeat count for a repeating vector expression.
3175+
fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr, span: span) -> uint {
3176+
match const_eval::eval_const_expr(tcx, count_expr) {
3177+
const_eval::const_int(count) => return count as uint,
3178+
const_eval::const_uint(count) => return count as uint,
3179+
const_eval::const_float(count) => {
3180+
tcx.sess.span_err(span,
3181+
~"expected signed or unsigned integer for \
3182+
repeat count but found float");
3183+
return count as uint;
3184+
}
3185+
const_eval::const_str(_) => {
3186+
tcx.sess.span_err(span,
3187+
~"expected signed or unsigned integer for \
3188+
repeat count but found string");
3189+
return 0;
3190+
}
3191+
}
3192+
}
3193+
31733194
// Local Variables:
31743195
// mode: rust
31753196
// fill-column: 78;

src/rustc/middle/typeck/check.rs

+2-22
Original file line numberDiff line numberDiff line change
@@ -1150,26 +1150,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
11501150
is_loop_body, some(fcx));
11511151
}
11521152

1153-
fn eval_repeat_count(fcx: @fn_ctxt, count_expr: @ast::expr, span: span)
1154-
-> uint {
1155-
let tcx = fcx.ccx.tcx;
1156-
match const_eval::eval_const_expr(tcx, count_expr) {
1157-
const_eval::const_int(count) => return count as uint,
1158-
const_eval::const_uint(count) => return count as uint,
1159-
const_eval::const_float(count) => {
1160-
tcx.sess.span_err(span,
1161-
~"expected signed or unsigned integer for \
1162-
repeat count but found float");
1163-
return count as uint;
1164-
}
1165-
const_eval::const_str(_) => {
1166-
tcx.sess.span_err(span,
1167-
~"expected signed or unsigned integer for \
1168-
repeat count but found string");
1169-
return 0;
1170-
}
1171-
}
1172-
}
11731153

11741154
// Check field access expressions
11751155
fn check_field(fcx: @fn_ctxt, expr: @ast::expr, is_callee: bool,
@@ -1284,7 +1264,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
12841264
ty::mk_evec(tcx, {ty: t, mutbl: mutbl}, tt)
12851265
}
12861266
ast::expr_repeat(element, count_expr, mutbl) => {
1287-
let count = eval_repeat_count(fcx, count_expr, expr.span);
1267+
let count = ty::eval_repeat_count(tcx, count_expr, expr.span);
12881268
fcx.write_ty(count_expr.id, ty::mk_uint(tcx));
12891269
let tt = ast_expr_vstore_to_vstore(fcx, ev, count, vst);
12901270
let t: ty::t = fcx.infcx.next_ty_var();
@@ -1642,7 +1622,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
16421622
fcx.write_ty(id, typ);
16431623
}
16441624
ast::expr_repeat(element, count_expr, mutbl) {
1645-
let count = eval_repeat_count(fcx, count_expr, expr.span);
1625+
let count = ty::eval_repeat_count(tcx, count_expr, expr.span);
16461626
fcx.write_ty(count_expr.id, ty::mk_uint(tcx));
16471627
let t: ty::t = fcx.infcx.next_ty_var();
16481628
bot |= check_expr_with(fcx, element, t);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
let x = [ @[true], ..512 ];
3+
let y = [ 0, ..1 ];
4+
error!("%?", x);
5+
error!("%?", y);
6+
}
7+

0 commit comments

Comments
 (0)