rustc: Translate repeated vector syntax
This commit is contained in:
parent
488ece05b5
commit
51a5a4ad0e
5 changed files with 106 additions and 45 deletions
|
@ -3636,8 +3636,13 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
||||||
}
|
}
|
||||||
ast::expr_lit(lit) { return trans_lit(bcx, e, *lit, dest); }
|
ast::expr_lit(lit) { return trans_lit(bcx, e, *lit, dest); }
|
||||||
ast::expr_vec(args, _) {
|
ast::expr_vec(args, _) {
|
||||||
return tvec::trans_evec(bcx, args, ast::vstore_fixed(none),
|
return tvec::trans_evec(bcx, tvec::individual_evec(args),
|
||||||
e.id, dest);
|
ast::vstore_fixed(none), e.id, dest);
|
||||||
|
}
|
||||||
|
ast::expr_repeat(element, count_expr, _) {
|
||||||
|
let count = ty::eval_repeat_count(bcx.tcx(), count_expr, e.span);
|
||||||
|
return tvec::trans_evec(bcx, tvec::repeating_evec(element, count),
|
||||||
|
ast::vstore_fixed(none), e.id, dest);
|
||||||
}
|
}
|
||||||
ast::expr_binary(op, lhs, rhs) {
|
ast::expr_binary(op, lhs, rhs) {
|
||||||
return trans_binary(bcx, op, lhs, rhs, dest, e);
|
return trans_binary(bcx, op, lhs, rhs, dest, e);
|
||||||
|
|
|
@ -5,7 +5,7 @@ import back::abi;
|
||||||
import base::{call_memmove,
|
import base::{call_memmove,
|
||||||
INIT, copy_val, load_if_immediate, get_tydesc,
|
INIT, copy_val, load_if_immediate, get_tydesc,
|
||||||
sub_block, do_spill_noroot,
|
sub_block, do_spill_noroot,
|
||||||
dest, bcx_icx, non_gc_box_cast};
|
dest, bcx_icx, non_gc_box_cast, move_val, lval_owned};
|
||||||
import syntax::codemap::span;
|
import syntax::codemap::span;
|
||||||
import shape::llsize_of;
|
import shape::llsize_of;
|
||||||
import build::*;
|
import build::*;
|
||||||
|
@ -118,18 +118,39 @@ fn make_drop_glue_unboxed(bcx: block, vptr: ValueRef, vec_ty: ty::t) ->
|
||||||
} else { bcx }
|
} else { bcx }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_evec(bcx: block, args: ~[@ast::expr],
|
enum evec_elements {
|
||||||
|
individual_evec(~[@ast::expr]),
|
||||||
|
repeating_evec(@ast::expr, uint)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trans_evec(bcx: block, elements: evec_elements,
|
||||||
vst: ast::vstore, id: ast::node_id, dest: dest) -> block {
|
vst: ast::vstore, id: ast::node_id, dest: dest) -> block {
|
||||||
let _icx = bcx.insn_ctxt(~"tvec::trans_evec");
|
let _icx = bcx.insn_ctxt(~"tvec::trans_evec");
|
||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
let mut bcx = bcx;
|
let mut bcx = bcx;
|
||||||
|
|
||||||
|
// Handle the ignored case.
|
||||||
if dest == base::ignore {
|
if dest == base::ignore {
|
||||||
for vec::each(args) |arg| {
|
match elements {
|
||||||
bcx = base::trans_expr(bcx, arg, base::ignore);
|
individual_evec(args) => {
|
||||||
|
for vec::each(args) |arg| {
|
||||||
|
bcx = base::trans_expr(bcx, arg, base::ignore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repeating_evec(element, _) => {
|
||||||
|
bcx = base::trans_expr(bcx, element, base::ignore);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return bcx;
|
return bcx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Figure out the number of elements we need.
|
||||||
|
let count;
|
||||||
|
match elements {
|
||||||
|
individual_evec(args) => count = args.len(),
|
||||||
|
repeating_evec(_, len) => count = len
|
||||||
|
}
|
||||||
|
|
||||||
let vec_ty = node_id_type(bcx, id);
|
let vec_ty = node_id_type(bcx, id);
|
||||||
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
||||||
let llunitty = type_of::type_of(ccx, unit_ty);
|
let llunitty = type_of::type_of(ccx, unit_ty);
|
||||||
|
@ -151,13 +172,12 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
|
||||||
{bcx: bcx, val: v, dataptr: v}
|
{bcx: bcx, val: v, dataptr: v}
|
||||||
}
|
}
|
||||||
ast::vstore_slice(_) {
|
ast::vstore_slice(_) {
|
||||||
let n = vec::len(args);
|
|
||||||
// Make a fake type to use for the cleanup
|
// Make a fake type to use for the cleanup
|
||||||
let ty = ty::mk_evec(bcx.tcx(),
|
let ty = ty::mk_evec(bcx.tcx(),
|
||||||
{ty: unit_ty, mutbl: ast::m_mutbl},
|
{ty: unit_ty, mutbl: ast::m_mutbl},
|
||||||
ty::vstore_fixed(n));
|
ty::vstore_fixed(count));
|
||||||
|
|
||||||
let n = C_uint(ccx, n);
|
let n = C_uint(ccx, count);
|
||||||
let vp = base::arrayalloca(bcx, llunitty, n);
|
let vp = base::arrayalloca(bcx, llunitty, n);
|
||||||
add_clean(bcx, vp, ty);
|
add_clean(bcx, vp, ty);
|
||||||
|
|
||||||
|
@ -171,15 +191,13 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
|
||||||
{bcx: bcx, val: p, dataptr: vp}
|
{bcx: bcx, val: p, dataptr: vp}
|
||||||
}
|
}
|
||||||
ast::vstore_uniq {
|
ast::vstore_uniq {
|
||||||
let {bcx, val} = alloc_vec(bcx, unit_ty, args.len(),
|
let {bcx, val} = alloc_vec(bcx, unit_ty, count, heap_exchange);
|
||||||
heap_exchange);
|
|
||||||
add_clean_free(bcx, val, heap_exchange);
|
add_clean_free(bcx, val, heap_exchange);
|
||||||
let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val));
|
let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val));
|
||||||
{bcx: bcx, val: val, dataptr: dataptr}
|
{bcx: bcx, val: val, dataptr: dataptr}
|
||||||
}
|
}
|
||||||
ast::vstore_box {
|
ast::vstore_box {
|
||||||
let {bcx, val} = alloc_vec(bcx, unit_ty, args.len(),
|
let {bcx, val} = alloc_vec(bcx, unit_ty, count, heap_shared);
|
||||||
heap_shared);
|
|
||||||
add_clean_free(bcx, val, heap_shared);
|
add_clean_free(bcx, val, heap_shared);
|
||||||
let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val));
|
let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val));
|
||||||
{bcx: bcx, val: val, dataptr: dataptr}
|
{bcx: bcx, val: val, dataptr: dataptr}
|
||||||
|
@ -192,12 +210,38 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
|
||||||
debug!{"trans_evec: v: %s, dataptr: %s",
|
debug!{"trans_evec: v: %s, dataptr: %s",
|
||||||
val_str(ccx.tn, val),
|
val_str(ccx.tn, val),
|
||||||
val_str(ccx.tn, dataptr)};
|
val_str(ccx.tn, dataptr)};
|
||||||
for vec::each(args) |e| {
|
match elements {
|
||||||
let lleltptr = InBoundsGEP(bcx, dataptr, ~[C_uint(ccx, i)]);
|
individual_evec(args) => {
|
||||||
bcx = base::trans_expr_save_in(bcx, e, lleltptr);
|
for vec::each(args) |e| {
|
||||||
add_clean_temp_mem(bcx, lleltptr, unit_ty);
|
let lleltptr = InBoundsGEP(bcx, dataptr, ~[C_uint(ccx, i)]);
|
||||||
vec::push(temp_cleanups, lleltptr);
|
bcx = base::trans_expr_save_in(bcx, e, lleltptr);
|
||||||
i += 1u;
|
add_clean_temp_mem(bcx, lleltptr, unit_ty);
|
||||||
|
vec::push(temp_cleanups, lleltptr);
|
||||||
|
i += 1u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repeating_evec(e, len) => {
|
||||||
|
// We make temporary space in the hope that this will be
|
||||||
|
// friendlier to LLVM alias analysis.
|
||||||
|
let lltmpspace = base::alloca(bcx, llunitty);
|
||||||
|
bcx = base::trans_expr_save_in(bcx, e, lltmpspace);
|
||||||
|
add_clean_temp_mem(bcx, lltmpspace, unit_ty);
|
||||||
|
vec::push(temp_cleanups, lltmpspace);
|
||||||
|
for len.timesi |i| {
|
||||||
|
let lleltptr = InBoundsGEP(bcx, dataptr, ~[C_uint(ccx, i)]);
|
||||||
|
if i == len - 1 {
|
||||||
|
// Move the last one in.
|
||||||
|
bcx = move_val(bcx, INIT, lleltptr,
|
||||||
|
lval_owned(bcx, lltmpspace), unit_ty);
|
||||||
|
} else {
|
||||||
|
// Copy all but the last one in.
|
||||||
|
let llval = load_if_immediate(bcx, lltmpspace, unit_ty);
|
||||||
|
bcx = copy_val(bcx, INIT, lleltptr, llval, unit_ty);
|
||||||
|
}
|
||||||
|
add_clean_temp_mem(bcx, lleltptr, unit_ty);
|
||||||
|
vec::push(temp_cleanups, lleltptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for vec::each(temp_cleanups) |cln| { revoke_clean(bcx, cln); }
|
for vec::each(temp_cleanups) |cln| { revoke_clean(bcx, cln); }
|
||||||
|
@ -219,13 +263,17 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
|
||||||
fn trans_vstore(bcx: block, e: @ast::expr,
|
fn trans_vstore(bcx: block, e: @ast::expr,
|
||||||
v: ast::vstore, dest: dest) -> block {
|
v: ast::vstore, dest: dest) -> block {
|
||||||
alt e.node {
|
alt e.node {
|
||||||
ast::expr_lit(@{node: ast::lit_str(s), span: _}) {
|
ast::expr_lit(@{node: ast::lit_str(s), span: _}) => {
|
||||||
return trans_estr(bcx, s, some(v), dest);
|
return trans_estr(bcx, s, some(v), dest);
|
||||||
}
|
}
|
||||||
ast::expr_vec(es, mutbl) {
|
ast::expr_vec(es, mutbl) => {
|
||||||
return trans_evec(bcx, es, v, e.id, dest);
|
return trans_evec(bcx, individual_evec(es), v, e.id, dest);
|
||||||
}
|
}
|
||||||
_ {
|
ast::expr_repeat(element, count_expr, mutbl) => {
|
||||||
|
let count = ty::eval_repeat_count(bcx.tcx(), count_expr, e.span);
|
||||||
|
return trans_evec(bcx, repeating_evec(element, count), v, e.id, dest);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
bcx.sess().span_bug(e.span, ~"vstore on non-sequence type");
|
bcx.sess().span_bug(e.span, ~"vstore on non-sequence type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,6 +169,7 @@ export terr_proto_mismatch;
|
||||||
export terr_ret_style_mismatch;
|
export terr_ret_style_mismatch;
|
||||||
export purity_to_str;
|
export purity_to_str;
|
||||||
export param_tys_in_type;
|
export param_tys_in_type;
|
||||||
|
export eval_repeat_count;
|
||||||
|
|
||||||
// Data types
|
// Data types
|
||||||
|
|
||||||
|
@ -3170,6 +3171,26 @@ fn normalize_ty(cx: ctxt, t: t) -> t {
|
||||||
return t_norm;
|
return t_norm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the repeat count for a repeating vector expression.
|
||||||
|
fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr, span: span) -> uint {
|
||||||
|
match const_eval::eval_const_expr(tcx, count_expr) {
|
||||||
|
const_eval::const_int(count) => return count as uint,
|
||||||
|
const_eval::const_uint(count) => return count as uint,
|
||||||
|
const_eval::const_float(count) => {
|
||||||
|
tcx.sess.span_err(span,
|
||||||
|
~"expected signed or unsigned integer for \
|
||||||
|
repeat count but found float");
|
||||||
|
return count as uint;
|
||||||
|
}
|
||||||
|
const_eval::const_str(_) => {
|
||||||
|
tcx.sess.span_err(span,
|
||||||
|
~"expected signed or unsigned integer for \
|
||||||
|
repeat count but found string");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// mode: rust
|
// mode: rust
|
||||||
// fill-column: 78;
|
// fill-column: 78;
|
||||||
|
|
|
@ -1150,26 +1150,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
||||||
is_loop_body, some(fcx));
|
is_loop_body, some(fcx));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_repeat_count(fcx: @fn_ctxt, count_expr: @ast::expr, span: span)
|
|
||||||
-> uint {
|
|
||||||
let tcx = fcx.ccx.tcx;
|
|
||||||
match const_eval::eval_const_expr(tcx, count_expr) {
|
|
||||||
const_eval::const_int(count) => return count as uint,
|
|
||||||
const_eval::const_uint(count) => return count as uint,
|
|
||||||
const_eval::const_float(count) => {
|
|
||||||
tcx.sess.span_err(span,
|
|
||||||
~"expected signed or unsigned integer for \
|
|
||||||
repeat count but found float");
|
|
||||||
return count as uint;
|
|
||||||
}
|
|
||||||
const_eval::const_str(_) => {
|
|
||||||
tcx.sess.span_err(span,
|
|
||||||
~"expected signed or unsigned integer for \
|
|
||||||
repeat count but found string");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check field access expressions
|
// Check field access expressions
|
||||||
fn check_field(fcx: @fn_ctxt, expr: @ast::expr, is_callee: bool,
|
fn check_field(fcx: @fn_ctxt, expr: @ast::expr, is_callee: bool,
|
||||||
|
@ -1284,7 +1264,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
||||||
ty::mk_evec(tcx, {ty: t, mutbl: mutbl}, tt)
|
ty::mk_evec(tcx, {ty: t, mutbl: mutbl}, tt)
|
||||||
}
|
}
|
||||||
ast::expr_repeat(element, count_expr, mutbl) => {
|
ast::expr_repeat(element, count_expr, mutbl) => {
|
||||||
let count = eval_repeat_count(fcx, count_expr, expr.span);
|
let count = ty::eval_repeat_count(tcx, count_expr, expr.span);
|
||||||
fcx.write_ty(count_expr.id, ty::mk_uint(tcx));
|
fcx.write_ty(count_expr.id, ty::mk_uint(tcx));
|
||||||
let tt = ast_expr_vstore_to_vstore(fcx, ev, count, vst);
|
let tt = ast_expr_vstore_to_vstore(fcx, ev, count, vst);
|
||||||
let t: ty::t = fcx.infcx.next_ty_var();
|
let t: ty::t = fcx.infcx.next_ty_var();
|
||||||
|
@ -1642,7 +1622,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
||||||
fcx.write_ty(id, typ);
|
fcx.write_ty(id, typ);
|
||||||
}
|
}
|
||||||
ast::expr_repeat(element, count_expr, mutbl) {
|
ast::expr_repeat(element, count_expr, mutbl) {
|
||||||
let count = eval_repeat_count(fcx, count_expr, expr.span);
|
let count = ty::eval_repeat_count(tcx, count_expr, expr.span);
|
||||||
fcx.write_ty(count_expr.id, ty::mk_uint(tcx));
|
fcx.write_ty(count_expr.id, ty::mk_uint(tcx));
|
||||||
let t: ty::t = fcx.infcx.next_ty_var();
|
let t: ty::t = fcx.infcx.next_ty_var();
|
||||||
bot |= check_expr_with(fcx, element, t);
|
bot |= check_expr_with(fcx, element, t);
|
||||||
|
|
7
src/test/run-pass/repeated-vector-syntax.rs
Normal file
7
src/test/run-pass/repeated-vector-syntax.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
fn main() {
|
||||||
|
let x = [ @[true], ..512 ];
|
||||||
|
let y = [ 0, ..1 ];
|
||||||
|
error!("%?", x);
|
||||||
|
error!("%?", y);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue