parent
15985277b9
commit
463cf837eb
2 changed files with 82 additions and 72 deletions
|
@ -354,10 +354,10 @@ fn pick_col(m: match) -> uint {
|
||||||
ret best_col;
|
ret best_col;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
|
fn compile_submatch(bcx: block, m: match, vals: [ValueRef],
|
||||||
&exits: [exit_node]) {
|
chk: option<mk_fail>, &exits: [exit_node]) {
|
||||||
let bcx = bcx, tcx = bcx.tcx(), dm = tcx.def_map;
|
let bcx = bcx, tcx = bcx.tcx(), dm = tcx.def_map;
|
||||||
if m.len() == 0u { Br(bcx, f()); ret; }
|
if m.len() == 0u { Br(bcx, option::get(chk)()); ret; }
|
||||||
if m[0].pats.len() == 0u {
|
if m[0].pats.len() == 0u {
|
||||||
let data = m[0].data;
|
let data = m[0].data;
|
||||||
alt data.guard {
|
alt data.guard {
|
||||||
|
@ -372,7 +372,7 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
|
||||||
trans_temp_expr(bcx, e)
|
trans_temp_expr(bcx, e)
|
||||||
};
|
};
|
||||||
bcx = with_cond(guard_cx, Not(guard_cx, val)) {|bcx|
|
bcx = with_cond(guard_cx, Not(guard_cx, val)) {|bcx|
|
||||||
compile_submatch(bcx, vec::tail(m), vals, f, exits);
|
compile_submatch(bcx, vec::tail(m), vals, chk, exits);
|
||||||
bcx
|
bcx
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -389,13 +389,10 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
|
||||||
let val = vals[col];
|
let val = vals[col];
|
||||||
let m = if has_nested_bindings(m, col) {
|
let m = if has_nested_bindings(m, col) {
|
||||||
expand_nested_bindings(m, col, val)
|
expand_nested_bindings(m, col, val)
|
||||||
} else {
|
} else { m };
|
||||||
m
|
|
||||||
};
|
|
||||||
|
|
||||||
let vals_left =
|
let vals_left = vec::slice(vals, 0u, col) +
|
||||||
vec::slice(vals, 0u, col) +
|
vec::slice(vals, col + 1u, vals.len());
|
||||||
vec::slice(vals, col + 1u, vals.len());
|
|
||||||
let ccx = bcx.fcx.ccx;
|
let ccx = bcx.fcx.ccx;
|
||||||
let pat_id = 0;
|
let pat_id = 0;
|
||||||
for br: match_branch in m {
|
for br: match_branch in m {
|
||||||
|
@ -417,7 +414,7 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
|
||||||
bcx = r.bcx;
|
bcx = r.bcx;
|
||||||
}
|
}
|
||||||
compile_submatch(bcx, enter_rec(dm, m, col, rec_fields, val),
|
compile_submatch(bcx, enter_rec(dm, m, col, rec_fields, val),
|
||||||
rec_vals + vals_left, f, exits);
|
rec_vals + vals_left, chk, exits);
|
||||||
ret;
|
ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,7 +432,7 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
compile_submatch(bcx, enter_tup(dm, m, col, val, n_tup_elts),
|
compile_submatch(bcx, enter_tup(dm, m, col, val, n_tup_elts),
|
||||||
tup_vals + vals_left, f, exits);
|
tup_vals + vals_left, chk, exits);
|
||||||
ret;
|
ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,14 +441,14 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
|
||||||
let box = Load(bcx, val);
|
let box = Load(bcx, val);
|
||||||
let unboxed = GEPi(bcx, box, [0, abi::box_field_body]);
|
let unboxed = GEPi(bcx, box, [0, abi::box_field_body]);
|
||||||
compile_submatch(bcx, enter_box(dm, m, col, val), [unboxed]
|
compile_submatch(bcx, enter_box(dm, m, col, val), [unboxed]
|
||||||
+ vals_left, f, exits);
|
+ vals_left, chk, exits);
|
||||||
ret;
|
ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if any_uniq_pat(m, col) {
|
if any_uniq_pat(m, col) {
|
||||||
let unboxed = Load(bcx, val);
|
let unboxed = Load(bcx, val);
|
||||||
compile_submatch(bcx, enter_uniq(dm, m, col, val),
|
compile_submatch(bcx, enter_uniq(dm, m, col, val),
|
||||||
[unboxed] + vals_left, f, exits);
|
[unboxed] + vals_left, chk, exits);
|
||||||
ret;
|
ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,42 +496,48 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
|
||||||
Switch(bcx, test_val, else_cx.llbb, opts.len())
|
Switch(bcx, test_val, else_cx.llbb, opts.len())
|
||||||
} else { C_int(ccx, 0) }; // Placeholder for when not using a switch
|
} else { C_int(ccx, 0) }; // Placeholder for when not using a switch
|
||||||
|
|
||||||
// Compile subtrees for each option
|
let defaults = enter_default(dm, m, col, val);
|
||||||
for opt: opt in opts {
|
let exhaustive = option::is_none(chk) && defaults.len() == 0u;
|
||||||
let opt_cx = sub_block(bcx, "match_case");
|
let len = opts.len(), i = 0u;
|
||||||
alt kind {
|
// Compile subtrees for each option
|
||||||
single { Br(bcx, opt_cx.llbb); }
|
for opt in opts {
|
||||||
switch {
|
i += 1u;
|
||||||
let res = trans_opt(bcx, opt);
|
let opt_cx = else_cx;
|
||||||
alt check res {
|
if !exhaustive || i < len {
|
||||||
single_result(r) {
|
opt_cx = sub_block(bcx, "match_case");
|
||||||
llvm::LLVMAddCase(sw, r.val, opt_cx.llbb);
|
alt kind {
|
||||||
bcx = r.bcx;
|
single { Br(bcx, opt_cx.llbb); }
|
||||||
}
|
switch {
|
||||||
}
|
alt check trans_opt(bcx, opt) {
|
||||||
}
|
single_result(r) {
|
||||||
compare {
|
llvm::LLVMAddCase(sw, r.val, opt_cx.llbb);
|
||||||
let t = node_id_type(bcx, pat_id);
|
bcx = r.bcx;
|
||||||
let {bcx: after_cx, val: matches} =
|
|
||||||
with_scope_result(bcx, "compare_scope") {|bcx|
|
|
||||||
alt trans_opt(bcx, opt) {
|
|
||||||
single_result({bcx, val}) {
|
|
||||||
trans_compare(bcx, ast::eq, test_val, t, val, t)
|
|
||||||
}
|
|
||||||
range_result({val: vbegin, _}, {bcx, val: vend}) {
|
|
||||||
let {bcx, val: ge} = trans_compare(bcx, ast::ge, test_val,
|
|
||||||
t, vbegin, t);
|
|
||||||
let {bcx, val: le} = trans_compare(bcx, ast::le, test_val,
|
|
||||||
t, vend, t);
|
|
||||||
{bcx: bcx, val: And(bcx, ge, le)}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
bcx = sub_block(after_cx, "compare_next");
|
compare {
|
||||||
CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
|
let t = node_id_type(bcx, pat_id);
|
||||||
}
|
let {bcx: after_cx, val: matches} =
|
||||||
_ { }
|
with_scope_result(bcx, "compare_scope") {|bcx|
|
||||||
}
|
alt trans_opt(bcx, opt) {
|
||||||
|
single_result({bcx, val}) {
|
||||||
|
trans_compare(bcx, ast::eq, test_val, t, val, t)
|
||||||
|
}
|
||||||
|
range_result({val: vbegin, _}, {bcx, val: vend}) {
|
||||||
|
let {bcx, val: ge} = trans_compare(
|
||||||
|
bcx, ast::ge, test_val, t, vbegin, t);
|
||||||
|
let {bcx, val: le} = trans_compare(
|
||||||
|
bcx, ast::le, test_val, t, vend, t);
|
||||||
|
{bcx: bcx, val: And(bcx, ge, le)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
bcx = sub_block(after_cx, "compare_next");
|
||||||
|
CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
|
||||||
|
}
|
||||||
|
_ { }
|
||||||
|
}
|
||||||
|
} else if kind == compare { Br(bcx, else_cx.llbb); }
|
||||||
let size = 0u;
|
let size = 0u;
|
||||||
let unpacked = [];
|
let unpacked = [];
|
||||||
alt opt {
|
alt opt {
|
||||||
|
@ -547,14 +550,15 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], f: mk_fail,
|
||||||
lit(_) | range(_, _) { }
|
lit(_) | range(_, _) { }
|
||||||
}
|
}
|
||||||
compile_submatch(opt_cx, enter_opt(tcx, m, opt, col, size, val),
|
compile_submatch(opt_cx, enter_opt(tcx, m, opt, col, size, val),
|
||||||
unpacked + vals_left, f, exits);
|
unpacked + vals_left, chk, exits);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile the fall-through case
|
// Compile the fall-through case, if any
|
||||||
if kind == compare { Br(bcx, else_cx.llbb); }
|
if !exhaustive {
|
||||||
if kind != single {
|
if kind == compare { Br(bcx, else_cx.llbb); }
|
||||||
compile_submatch(else_cx, enter_default(dm, m, col, val), vals_left,
|
if kind != single {
|
||||||
f, exits);
|
compile_submatch(else_cx, defaults, vals_left, chk, exits);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,12 +609,14 @@ fn make_phi_bindings(bcx: block, map: [exit_node],
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_alt(bcx: block, expr: @ast::expr, arms: [ast::arm],
|
fn trans_alt(bcx: block, expr: @ast::expr, arms: [ast::arm],
|
||||||
dest: dest) -> block {
|
mode: ast::alt_mode, dest: dest) -> block {
|
||||||
with_scope(bcx, "alt") {|bcx| trans_alt_inner(bcx, expr, arms, dest)}
|
with_scope(bcx, "alt") {|bcx|
|
||||||
|
trans_alt_inner(bcx, expr, arms, mode, dest)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_alt_inner(scope_cx: block, expr: @ast::expr, arms: [ast::arm],
|
fn trans_alt_inner(scope_cx: block, expr: @ast::expr, arms: [ast::arm],
|
||||||
dest: dest) -> block {
|
mode: ast::alt_mode, dest: dest) -> block {
|
||||||
let bcx = scope_cx, tcx = bcx.tcx();
|
let bcx = scope_cx, tcx = bcx.tcx();
|
||||||
let bodies = [], match = [];
|
let bodies = [], match = [];
|
||||||
|
|
||||||
|
@ -630,22 +636,26 @@ fn trans_alt_inner(scope_cx: block, expr: @ast::expr, arms: [ast::arm],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cached fail-on-fallthrough block
|
let mk_fail = alt mode {
|
||||||
let fail_cx = @mutable none;
|
ast::alt_check {
|
||||||
fn mk_fail(bcx: block, sp: span,
|
// Cached fail-on-fallthrough block
|
||||||
done: @mutable option<BasicBlockRef>) -> BasicBlockRef {
|
let fail_cx = @mutable none;
|
||||||
alt *done { some(bb) { ret bb; } _ { } }
|
fn mk_fail(bcx: block, sp: span,
|
||||||
let fail_cx = sub_block(bcx, "case_fallthrough");
|
done: @mutable option<BasicBlockRef>) -> BasicBlockRef {
|
||||||
trans_fail(fail_cx, some(sp), "non-exhaustive match failure");;
|
alt *done { some(bb) { ret bb; } _ { } }
|
||||||
*done = some(fail_cx.llbb);
|
let fail_cx = sub_block(bcx, "case_fallthrough");
|
||||||
ret fail_cx.llbb;
|
trans_fail(fail_cx, some(sp), "non-exhaustive match failure");;
|
||||||
}
|
*done = some(fail_cx.llbb);
|
||||||
|
ret fail_cx.llbb;
|
||||||
|
}
|
||||||
|
some(bind mk_fail(scope_cx, expr.span, fail_cx))
|
||||||
|
}
|
||||||
|
ast::alt_exhaustive { none }
|
||||||
|
};
|
||||||
let exit_map = [];
|
let exit_map = [];
|
||||||
let t = node_id_type(bcx, expr.id);
|
let t = node_id_type(bcx, expr.id);
|
||||||
let {bcx, val: spilled} = spill_if_immediate(bcx, val, t);
|
let {bcx, val: spilled} = spill_if_immediate(bcx, val, t);
|
||||||
compile_submatch(bcx, match, [spilled],
|
compile_submatch(bcx, match, [spilled], mk_fail, exit_map);
|
||||||
bind mk_fail(scope_cx, expr.span, fail_cx), exit_map);
|
|
||||||
|
|
||||||
let arm_cxs = [], arm_dests = [], i = 0u;
|
let arm_cxs = [], arm_dests = [], i = 0u;
|
||||||
for a in arms {
|
for a in arms {
|
||||||
|
|
|
@ -3141,8 +3141,8 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
||||||
ast::expr_if(cond, thn, els) | ast::expr_if_check(cond, thn, els) {
|
ast::expr_if(cond, thn, els) | ast::expr_if_check(cond, thn, els) {
|
||||||
ret trans_if(bcx, cond, thn, els, dest);
|
ret trans_if(bcx, cond, thn, els, dest);
|
||||||
}
|
}
|
||||||
ast::expr_alt(expr, arms, _) {
|
ast::expr_alt(expr, arms, mode) {
|
||||||
ret alt::trans_alt(bcx, expr, arms, dest);
|
ret alt::trans_alt(bcx, expr, arms, mode, dest);
|
||||||
}
|
}
|
||||||
ast::expr_block(blk) {
|
ast::expr_block(blk) {
|
||||||
ret with_scope(bcx, "block-expr body") {|bcx|
|
ret with_scope(bcx, "block-expr body") {|bcx|
|
||||||
|
|
Loading…
Reference in a new issue