aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2011-02-28 17:49:26 -0800
committerGraydon Hoare <[email protected]>2011-02-28 17:49:26 -0800
commitd08f3a1c702c337c494bbc03d8bed9664ac1dddf (patch)
tree24a0e22330b4d0ac314432599a79e33f0024a704 /src
parentGroundwork for structural comparison. Still lacking the actual loop that does... (diff)
downloadrust-d08f3a1c702c337c494bbc03d8bed9664ac1dddf.tar.xz
rust-d08f3a1c702c337c494bbc03d8bed9664ac1dddf.zip
More complete sketch of structural compare. Still not quite working.
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/trans.rs153
1 files changed, 115 insertions, 38 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 4a45beea..8dc4efb7 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -1493,27 +1493,50 @@ fn mk_plain_tag(ast.def_id tid) -> @ty.t {
type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result;
+type val_pair_and_ty_fn =
+ fn(@block_ctxt cx, ValueRef av, ValueRef bv, @ty.t t) -> result;
+
// Iterates through the elements of a structural type.
fn iter_structural_ty(@block_ctxt cx,
ValueRef v,
@ty.t t,
val_and_ty_fn f)
-> result {
+ fn adaptor_fn(val_and_ty_fn f,
+ @block_ctxt cx,
+ ValueRef av,
+ ValueRef bv,
+ @ty.t t) -> result {
+ ret f(cx, av, t);
+ }
+ be iter_structural_ty_full(cx, v, v, t,
+ bind adaptor_fn(f, _, _, _, _));
+}
+
+
+fn iter_structural_ty_full(@block_ctxt cx,
+ ValueRef av,
+ ValueRef bv,
+ @ty.t t,
+ val_pair_and_ty_fn f)
+ -> result {
let result r = res(cx, C_nil());
fn iter_boxpp(@block_ctxt cx,
- ValueRef box_cell,
- val_and_ty_fn f) -> result {
- auto box_ptr = cx.build.Load(box_cell);
+ ValueRef box_a_cell,
+ ValueRef box_b_cell,
+ val_pair_and_ty_fn f) -> result {
+ auto box_a_ptr = cx.build.Load(box_a_cell);
+ auto box_b_ptr = cx.build.Load(box_b_cell);
auto tnil = plain_ty(ty.ty_nil);
auto tbox = plain_ty(ty.ty_box(tnil));
auto inner_cx = new_sub_block_ctxt(cx, "iter box");
auto next_cx = new_sub_block_ctxt(cx, "next");
- auto null_test = cx.build.IsNull(box_ptr);
+ auto null_test = cx.build.IsNull(box_a_ptr);
cx.build.CondBr(null_test, next_cx.llbb, inner_cx.llbb);
- auto r = f(inner_cx, box_ptr, tbox);
+ auto r = f(inner_cx, box_a_ptr, box_b_ptr, tbox);
r.bcx.build.Br(next_cx.llbb);
ret res(next_cx, r.val);
}
@@ -1522,9 +1545,11 @@ fn iter_structural_ty(@block_ctxt cx,
case (ty.ty_tup(?args)) {
let int i = 0;
for (@ty.t arg in args) {
- auto elt = r.bcx.build.GEP(v, vec(C_int(0), C_int(i)));
+ auto elt_a = r.bcx.build.GEP(av, vec(C_int(0), C_int(i)));
+ auto elt_b = r.bcx.build.GEP(bv, vec(C_int(0), C_int(i)));
r = f(r.bcx,
- load_scalar_or_boxed(r.bcx, elt, arg),
+ load_scalar_or_boxed(r.bcx, elt_a, arg),
+ load_scalar_or_boxed(r.bcx, elt_b, arg),
arg);
i += 1;
}
@@ -1532,9 +1557,11 @@ fn iter_structural_ty(@block_ctxt cx,
case (ty.ty_rec(?fields)) {
let int i = 0;
for (ty.field fld in fields) {
- auto llfld = r.bcx.build.GEP(v, vec(C_int(0), C_int(i)));
+ auto llfld_a = r.bcx.build.GEP(av, vec(C_int(0), C_int(i)));
+ auto llfld_b = r.bcx.build.GEP(bv, vec(C_int(0), C_int(i)));
r = f(r.bcx,
- load_scalar_or_boxed(r.bcx, llfld, fld.ty),
+ load_scalar_or_boxed(r.bcx, llfld_a, fld.ty),
+ load_scalar_or_boxed(r.bcx, llfld_b, fld.ty),
fld.ty);
i += 1;
}
@@ -1545,53 +1572,69 @@ fn iter_structural_ty(@block_ctxt cx,
auto variants = tag_variants(cx.fcx.ccx, tid);
auto n_variants = _vec.len[ast.variant](variants);
- auto lldiscrim_ptr = cx.build.GEP(v, vec(C_int(0), C_int(0)));
- auto llunion_ptr = cx.build.GEP(v, vec(C_int(0), C_int(1)));
- auto lldiscrim = cx.build.Load(lldiscrim_ptr);
+ auto lldiscrim_a_ptr = cx.build.GEP(av, vec(C_int(0), C_int(0)));
+ auto llunion_a_ptr = cx.build.GEP(av, vec(C_int(0), C_int(1)));
+ auto lldiscrim_a = cx.build.Load(lldiscrim_a_ptr);
+
+ auto lldiscrim_b_ptr = cx.build.GEP(bv, vec(C_int(0), C_int(0)));
+ auto llunion_b_ptr = cx.build.GEP(bv, vec(C_int(0), C_int(1)));
+ auto lldiscrim_b = cx.build.Load(lldiscrim_b_ptr);
auto unr_cx = new_sub_block_ctxt(cx, "tag-iter-unr");
unr_cx.build.Unreachable();
- auto llswitch = cx.build.Switch(lldiscrim, unr_cx.llbb,
- n_variants);
+ auto llswitch = cx.build.Switch(lldiscrim_a, unr_cx.llbb,
+ n_variants);
auto next_cx = new_sub_block_ctxt(cx, "tag-iter-next");
auto i = 0u;
for (ast.variant variant in variants) {
- auto variant_cx = new_sub_block_ctxt(cx, "tag-iter-variant-" +
+ auto variant_cx = new_sub_block_ctxt(cx,
+ "tag-iter-variant-" +
_uint.to_str(i, 10u));
llvm.LLVMAddCase(llswitch, C_int(i as int), variant_cx.llbb);
if (_vec.len[ast.variant_arg](variant.args) > 0u) {
// N-ary variant.
- let vec[ValueRef] vals = vec(C_int(0), C_int(1),
- C_int(i as int));
- auto llvar = variant_cx.build.GEP(v, vals);
auto llvarty = type_of_variant(cx.fcx.ccx, variants.(i));
auto fn_ty = ty.ann_to_type(variants.(i).ann);
alt (fn_ty.struct) {
case (ty.ty_fn(_, ?args, _)) {
- auto llvarp = variant_cx.build.
- TruncOrBitCast(llunion_ptr, T_ptr(llvarty));
+ auto llvarp_a = variant_cx.build.
+ TruncOrBitCast(llunion_a_ptr, T_ptr(llvarty));
+
+ auto llvarp_b = variant_cx.build.
+ TruncOrBitCast(llunion_b_ptr, T_ptr(llvarty));
auto ty_params = tag_ty_params(cx.fcx.ccx, tid);
auto j = 0u;
for (ty.arg a in args) {
auto v = vec(C_int(0), C_int(j as int));
- auto llfldp = variant_cx.build.GEP(llvarp, v);
+
+ auto llfldp_a =
+ variant_cx.build.GEP(llvarp_a, v);
+
+ auto llfldp_b =
+ variant_cx.build.GEP(llvarp_b, v);
auto ty_subst = ty.substitute_ty_params(
ty_params, tps, a.ty);
- auto llfld =
+ auto llfld_a =
load_scalar_or_boxed(variant_cx,
- llfldp,
+ llfldp_a,
ty_subst);
- auto res = f(variant_cx, llfld, ty_subst);
+ auto llfld_b =
+ load_scalar_or_boxed(variant_cx,
+ llfldp_b,
+ ty_subst);
+
+ auto res = f(variant_cx,
+ llfld_a, llfld_b, ty_subst);
variant_cx = res.bcx;
j += 1u;
}
@@ -1611,21 +1654,29 @@ fn iter_structural_ty(@block_ctxt cx,
ret res(next_cx, C_nil());
}
case (ty.ty_fn(_,_,_)) {
- auto box_cell =
- cx.build.GEP(v,
+ auto box_cell_a =
+ cx.build.GEP(av,
+ vec(C_int(0),
+ C_int(abi.fn_field_box)));
+ auto box_cell_b =
+ cx.build.GEP(bv,
vec(C_int(0),
C_int(abi.fn_field_box)));
- ret iter_boxpp(cx, box_cell, f);
+ ret iter_boxpp(cx, box_cell_a, box_cell_b, f);
}
case (ty.ty_obj(_)) {
- auto box_cell =
- cx.build.GEP(v,
+ auto box_cell_a =
+ cx.build.GEP(av,
+ vec(C_int(0),
+ C_int(abi.obj_field_box)));
+ auto box_cell_b =
+ cx.build.GEP(bv,
vec(C_int(0),
C_int(abi.obj_field_box)));
- ret iter_boxpp(cx, box_cell, f);
+ ret iter_boxpp(cx, box_cell_a, box_cell_b, f);
}
case (_) {
- cx.fcx.ccx.sess.unimpl("type in iter_structural_ty");
+ cx.fcx.ccx.sess.unimpl("type in iter_structural_ty_full");
}
}
ret r;
@@ -1965,21 +2016,47 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t,
ret res(cx, trans_scalar_compare(cx, op, t, lhs, rhs));
} else if (ty.type_is_structural(t)) {
- auto scx = new_sub_block_ctxt(cx, "structural compare body");
- auto next = new_sub_block_ctxt(cx, "structural compare completion");
+ auto scx = new_sub_block_ctxt(cx, "structural compare start");
+ auto next = new_sub_block_ctxt(cx, "structural compare end");
cx.build.Br(scx.llbb);
// Start with the assumptioin that our predicate holds.
auto flag = scx.build.Alloca(T_i1());
scx.build.Store(C_integral(1, T_i1()), flag);
- // Attempt to prove otherwise by inverting the sense of the comparison
- // on each inner element and bailing if any succeed.
+ // Attempt to prove otherwise by assuming true, comparing each element
+ // and writing 0 + early-exiting if any comparisons fail.
+
+ fn inner(@block_ctxt next_cx,
+ ValueRef flag,
+ ast.binop op,
+ @block_ctxt cx,
+ ValueRef av,
+ ValueRef bv,
+ @ty.t t) -> result {
+ // Compare av op bv
+ auto cnt_cx = new_sub_block_ctxt(cx, "continue comparison");
+ auto stop_cx = new_sub_block_ctxt(cx, "stop comparison");
+
+ auto r = trans_compare(cx, op, t, av, bv);
+
+ // if true, then carry on, else write 0 to flag, branch to 'next'.
+ r.bcx.build.CondBr(r.val, cnt_cx.llbb, stop_cx.llbb);
+ stop_cx.build.Store(C_integral(0, T_i1()), flag);
+ stop_cx.build.Br(next_cx.llbb);
+
+ ret res(cnt_cx, C_nil());
+ }
+
+ // FIXME: this is wrong for tag types; need to confirm discriminants
+ // are equal before blindly walking over elements.
- // FIXME: finish this.
+ auto r = iter_structural_ty_full(scx, lhs, rhs, t,
+ bind inner(next, flag, op,
+ _, _, _, _));
- auto v = scx.build.Load(flag);
- scx.build.Br(next.llbb);
+ r.bcx.build.Br(next.llbb);
+ auto v = next.build.Load(flag);
ret res(next, v);
} else {