about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2011-02-28 17:49:26 -0800
committerGraydon Hoare <graydon@mozilla.com>2011-02-28 17:49:26 -0800
commitd08f3a1c702c337c494bbc03d8bed9664ac1dddf (patch)
tree24a0e22330b4d0ac314432599a79e33f0024a704 /src/comp
parent1291cc2df90c36eee8642048e1bf1b69a690781f (diff)
downloadrust-d08f3a1c702c337c494bbc03d8bed9664ac1dddf.tar.gz
rust-d08f3a1c702c337c494bbc03d8bed9664ac1dddf.zip
More complete sketch of structural compare. Still not quite working.
Diffstat (limited to 'src/comp')
-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 4a45beea1b0..8dc4efb74c2 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 {