about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2011-01-31 20:27:38 -0500
committerBrian Anderson <andersrb@gmail.com>2011-01-31 20:27:38 -0500
commitc848ed1e9862a527e0a6f16ef235b41f98baa419 (patch)
tree3ad344301bdcff06081a1a38d7cb709c08d66668
parent214c32393a9d28436dd782c9ea6e3e32d3baba2e (diff)
parent784b2decf2ce4233a022cf221b1ec744b755c3ed (diff)
downloadrust-c848ed1e9862a527e0a6f16ef235b41f98baa419.tar.gz
rust-c848ed1e9862a527e0a6f16ef235b41f98baa419.zip
Merge branch 'master' into forgraydon-elseif
-rw-r--r--.gitignore1
-rw-r--r--src/Makefile7
-rw-r--r--src/comp/middle/trans.rs270
-rw-r--r--src/test/compile-fail/infinite-vec-type-recursion.rs2
-rw-r--r--src/test/run-pass/many.rs4
-rw-r--r--src/test/run-pass/task-comm-10.rs4
-rw-r--r--src/test/run-pass/task-comm-15.rs4
-rw-r--r--src/test/run-pass/task-comm-3.rs6
-rw-r--r--src/test/run-pass/task-comm-8.rs6
-rw-r--r--src/test/run-pass/task-comm-9.rs6
-rw-r--r--src/test/run-pass/task-comm.rs14
11 files changed, 194 insertions, 130 deletions
diff --git a/.gitignore b/.gitignore
index 5626e0dcf1a..fbc2920fd60 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,7 @@
 *.tp
 *.vr
 *.swp
+*.tmp
 .hg/
 .hgignore
 .cproject
diff --git a/src/Makefile b/src/Makefile
index bd45d2531df..ac7dfcbbb71 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -510,10 +510,13 @@ TEST_XFAILS_RUSTC := $(filter-out \
                         writealias.rs \
                         ) \
                       $(addprefix test/compile-fail/, \
+                        alt-tag-nullary.rs \
+                        alt-tag-unary.rs \
                         arg-count-mismatch.rs \
                         arg-type-mismatch.rs \
                         bad-expr-path.rs \
                         bad-expr-path2.rs \
+                        bogus-tag.rs \
                         import.rs \
                         import2.rs \
                         import3.rs \
@@ -521,7 +524,11 @@ TEST_XFAILS_RUSTC := $(filter-out \
                         import-loop.rs \
                         import-loop-2.rs \
                         multiline-comment-line-tracking.rs \
+                        output-type-mismatch.rs \
+                        rec-missing-fields.rs \
+                        type-shadow.rs \
                         while-type-error.rs \
+                        wrong-ret-type.rs \
                         ), \
                       $(wildcard test/*/*.rs test/*/*.rc))
 
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index ee695b881fd..8eb614e5da3 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -63,6 +63,7 @@ type tag_info = rec(type_handle th,
 state type crate_ctxt = rec(session.session sess,
                             ModuleRef llmod,
                             target_data td,
+                            ValueRef crate_ptr,
                             hashmap[str, ValueRef] upcalls,
                             hashmap[str, ValueRef] intrinsics,
                             hashmap[str, ValueRef] item_names,
@@ -687,25 +688,25 @@ fn llalign_of(TypeRef t) -> ValueRef {
     ret llvm.LLVMConstIntCast(lib.llvm.llvm.LLVMAlignOf(t), T_int(), False);
 }
 
-fn size_of(@block_ctxt cx, @ty.t t) -> ValueRef {
+fn size_of(@block_ctxt cx, @ty.t t) -> result {
     if (!ty.type_has_dynamic_size(t)) {
-        ret llsize_of(type_of(cx.fcx.ccx, t));
+        ret res(cx, llsize_of(type_of(cx.fcx.ccx, t)));
     }
     ret dynamic_size_of(cx, t);
 }
 
-fn align_of(@block_ctxt cx, @ty.t t) -> ValueRef {
+fn align_of(@block_ctxt cx, @ty.t t) -> result {
     if (!ty.type_has_dynamic_size(t)) {
-        ret llalign_of(type_of(cx.fcx.ccx, t));
+        ret res(cx, llalign_of(type_of(cx.fcx.ccx, t)));
     }
     ret dynamic_align_of(cx, t);
 }
 
-fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> ValueRef {
+fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result {
     alt (t.struct) {
         case (ty.ty_param(?p)) {
             auto szptr = field_of_tydesc(cx, t, abi.tydesc_field_size);
-            ret cx.build.Load(szptr);
+            ret res(szptr.bcx, szptr.bcx.build.Load(szptr.val));
         }
         case (ty.ty_tup(?elts)) {
             //
@@ -718,51 +719,63 @@ fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> ValueRef {
             //
             auto off = C_int(0);
             auto max_align = C_int(1);
+            auto bcx = cx;
             for (@ty.t e in elts) {
-                auto elt_align = align_of(cx, e);
-                auto elt_size = size_of(cx, e);
-                auto aligned_off = align_to(cx, off, elt_align);
-                off = cx.build.Add(aligned_off, elt_size);
-                max_align = umax(cx, max_align, elt_align);
+                auto elt_align = align_of(bcx, e);
+                bcx = elt_align.bcx;
+                auto elt_size = size_of(bcx, e);
+                bcx = elt_size.bcx;
+                auto aligned_off = align_to(bcx, off, elt_align.val);
+                off = cx.build.Add(aligned_off, elt_size.val);
+                max_align = umax(bcx, max_align, elt_align.val);
             }
-            off = align_to(cx, off, max_align);
-            ret off;
+            off = align_to(bcx, off, max_align);
+            ret res(bcx, off);
         }
         case (ty.ty_rec(?flds)) {
             auto off = C_int(0);
             auto max_align = C_int(1);
+            auto bcx = cx;
             for (ty.field f in flds) {
-                auto elt_align = align_of(cx, f.ty);
-                auto elt_size = size_of(cx, f.ty);
-                auto aligned_off = align_to(cx, off, elt_align);
-                off = cx.build.Add(aligned_off, elt_size);
-                max_align = umax(cx, max_align, elt_align);
+                auto elt_align = align_of(bcx, f.ty);
+                bcx = elt_align.bcx;
+                auto elt_size = size_of(bcx, f.ty);
+                bcx = elt_size.bcx;
+                auto aligned_off = align_to(bcx, off, elt_align.val);
+                off = cx.build.Add(aligned_off, elt_size.val);
+                max_align = umax(bcx, max_align, elt_align.val);
             }
-            off = align_to(cx, off, max_align);
-            ret off;
+            off = align_to(bcx, off, max_align);
+            ret res(bcx, off);
         }
     }
 }
 
-fn dynamic_align_of(@block_ctxt cx, @ty.t t) -> ValueRef {
+fn dynamic_align_of(@block_ctxt cx, @ty.t t) -> result {
     alt (t.struct) {
         case (ty.ty_param(?p)) {
             auto aptr = field_of_tydesc(cx, t, abi.tydesc_field_align);
-            ret cx.build.Load(aptr);
+            ret res(aptr.bcx, aptr.bcx.build.Load(aptr.val));
         }
         case (ty.ty_tup(?elts)) {
             auto a = C_int(1);
+            auto bcx = cx;
             for (@ty.t e in elts) {
-                a = umax(cx, a, align_of(cx, e));
+                auto align = align_of(bcx, e);
+                bcx = align.bcx;
+                a = umax(bcx, a, align.val);
             }
-            ret a;
+            ret res(bcx, a);
         }
         case (ty.ty_rec(?flds)) {
             auto a = C_int(1);
+            auto bcx = cx;
             for (ty.field f in flds) {
-                a = umax(cx, a, align_of(cx, f.ty));
+                auto align = align_of(bcx, f.ty);
+                bcx = align.bcx;
+                a = umax(bcx, a, align.val);
             }
-            ret a;
+            ret res(bcx, a);
         }
     }
 }
@@ -774,7 +787,7 @@ fn dynamic_align_of(@block_ctxt cx, @ty.t t) -> ValueRef {
 // align_of, above.
 
 fn GEP_tup_like(@block_ctxt cx, @ty.t t,
-                ValueRef base, vec[int] ixs) -> ValueRef {
+                ValueRef base, vec[int] ixs) -> result {
 
     check (ty.type_is_tup_like(t));
 
@@ -785,7 +798,7 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t,
         for (int i in ixs) {
             v += C_int(i);
         }
-        ret cx.build.GEP(base, v);
+        ret res(cx, cx.build.GEP(base, v));
     }
 
     // It is a dynamic-containing type that, if we convert directly to an LLVM
@@ -856,14 +869,16 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t,
 
     auto s = split_type(t, ixs, 0u);
     auto prefix_ty = ty.plain_ty(ty.ty_tup(s.prefix));
-    auto sz = size_of(cx, prefix_ty);
-    auto raw = cx.build.PointerCast(base, T_ptr(T_i8()));
-    auto bumped = cx.build.GEP(raw, vec(sz));
+    auto bcx = cx;
+    auto sz = size_of(bcx, prefix_ty);
+    bcx = sz.bcx;
+    auto raw = bcx.build.PointerCast(base, T_ptr(T_i8()));
+    auto bumped = bcx.build.GEP(raw, vec(sz.val));
     alt (s.target.struct) {
-        case (ty.ty_param(_)) { ret bumped; }
+        case (ty.ty_param(_)) { ret res(bcx, bumped); }
         case (_) {
-            auto ty = T_ptr(type_of(cx.fcx.ccx, s.target));
-            ret cx.build.PointerCast(bumped, ty);
+            auto ty = T_ptr(type_of(bcx.fcx.ccx, s.target));
+            ret res(bcx, bcx.build.PointerCast(bumped, ty));
         }
     }
 }
@@ -893,9 +908,10 @@ fn trans_malloc(@block_ctxt cx, @ty.t t) -> result {
 // Given a type and a field index into its corresponding type descriptor,
 // returns an LLVM ValueRef of that field from the tydesc, generating the
 // tydesc if necessary.
-fn field_of_tydesc(@block_ctxt cx, @ty.t t, int field) -> ValueRef {
+fn field_of_tydesc(@block_ctxt cx, @ty.t t, int field) -> result {
     auto tydesc = get_tydesc(cx, t);
-    ret cx.build.GEP(tydesc, vec(C_int(0), C_int(field)));
+    ret res(tydesc.bcx,
+            tydesc.bcx.build.GEP(tydesc.val, vec(C_int(0), C_int(field))));
 }
 
 // Given a type containing ty params, build a vector containing a ValueRef for
@@ -940,10 +956,12 @@ fn linearize_ty_params(@block_ctxt cx, @ty.t t)
     ret tup(x.defs, x.vals);
 }
 
-fn get_tydesc(&@block_ctxt cx, @ty.t t) -> ValueRef {
+fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result {
     // Is the supplied type a type param? If so, return the passed-in tydesc.
     alt (ty.type_param(t)) {
-        case (some[ast.def_id](?id)) { ret cx.fcx.lltydescs.get(id); }
+        case (some[ast.def_id](?id)) {
+            ret res(cx, cx.fcx.lltydescs.get(id));
+        }
         case (none[ast.def_id])      { /* fall through */ }
     }
 
@@ -953,13 +971,36 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> ValueRef {
     if (ty.count_ty_params(t) > 0u) {
         auto tys = linearize_ty_params(cx, t);
 
+        check (n_params == _vec.len[ast.def_id](tys._0));
+        check (n_params == _vec.len[ValueRef](tys._1));
+
         if (!cx.fcx.ccx.tydescs.contains_key(t)) {
             make_tydesc(cx.fcx.ccx, t, tys._0);
         }
 
         auto root = cx.fcx.ccx.tydescs.get(t);
 
-        cx.fcx.ccx.sess.unimpl("derived type descriptors");
+        auto tydescs = cx.build.Alloca(T_array(T_ptr(T_tydesc()), n_params));
+        auto i = 0;
+        for (ValueRef td in tys._1) {
+            auto tdp = cx.build.GEP(tydescs, vec(C_int(0), C_int(i)));
+            cx.build.Store(td, tdp);
+        }
+
+        auto bcx = cx;
+        auto sz = size_of(bcx, t);
+        bcx = sz.bcx;
+        auto align = align_of(bcx, t);
+        bcx = align.bcx;
+
+        auto v = trans_upcall(bcx, "upcall_get_type_desc",
+                              vec(p2i(bcx.fcx.ccx.crate_ptr),
+                                  sz.val,
+                                  align.val,
+                                  C_int(n_params as int),
+                                  bcx.build.PtrToInt(tydescs, T_int())));
+
+        ret res(v.bcx, v.bcx.build.IntToPtr(v.val, T_ptr(T_tydesc())));
     }
 
     // Otherwise, generate a tydesc if necessary, and return it.
@@ -967,7 +1008,7 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> ValueRef {
         let vec[ast.def_id] defs = vec();
         make_tydesc(cx.fcx.ccx, t, defs);
     }
-    ret cx.fcx.ccx.tydescs.get(t);
+    ret res(cx, cx.fcx.ccx.tydescs.get(t));
 }
 
 fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) {
@@ -1437,20 +1478,20 @@ fn iter_sequence(@block_ctxt cx,
                                           C_int(abi.vec_elt_fill)));
 
         auto llunit_ty = type_of(cx.fcx.ccx, elt_ty);
-        auto unit_sz = size_of(cx, elt_ty);
+        auto bcx = cx;
+        auto unit_sz = size_of(bcx, elt_ty);
+        bcx = unit_sz.bcx;
 
-        auto len = cx.build.Load(lenptr);
+        auto len = bcx.build.Load(lenptr);
         if (trailing_null) {
-            len = cx.build.Sub(len, unit_sz);
+            len = bcx.build.Sub(len, unit_sz.val);
         }
 
-        auto r = res(cx, C_nil());
-
         auto cond_cx = new_scope_block_ctxt(cx, "sequence-iter cond");
         auto body_cx = new_scope_block_ctxt(cx, "sequence-iter body");
         auto next_cx = new_sub_block_ctxt(cx, "next");
 
-        cx.build.Br(cond_cx.llbb);
+        bcx.build.Br(cond_cx.llbb);
 
         auto ix = cond_cx.build.Phi(T_int(), vec(C_int(0)), vec(cx.llbb));
         auto scaled_ix = cond_cx.build.Phi(T_int(),
@@ -1465,7 +1506,7 @@ fn iter_sequence(@block_ctxt cx,
                           load_scalar_or_boxed(body_cx, elt, elt_ty),
                           elt_ty);
         auto next_ix = body_res.bcx.build.Add(ix, C_int(1));
-        auto next_scaled_ix = body_res.bcx.build.Add(scaled_ix, unit_sz);
+        auto next_scaled_ix = body_res.bcx.build.Add(scaled_ix, unit_sz.val);
 
         cond_cx.build.AddIncomingToPhi(ix, vec(next_ix),
                                        vec(body_res.bcx.llbb));
@@ -1504,7 +1545,8 @@ fn call_tydesc_glue_full(@block_ctxt cx, ValueRef v,
 }
 
 fn call_tydesc_glue(@block_ctxt cx, ValueRef v, @ty.t t, int field) {
-    call_tydesc_glue_full(cx, v, get_tydesc(cx, t), field);
+    auto td = get_tydesc(cx, t);
+    call_tydesc_glue_full(td.bcx, v, td.val, field);
 }
 
 fn incr_all_refcnts(@block_ctxt cx,
@@ -1565,8 +1607,8 @@ fn memcpy_ty(@block_ctxt cx,
              @ty.t t) -> result {
     if (ty.type_has_dynamic_size(t)) {
         auto llszptr = field_of_tydesc(cx, t, abi.tydesc_field_size);
-        auto llsz = cx.build.Load(llszptr);
-        ret call_memcpy(cx, dst, src, llsz);
+        auto llsz = llszptr.bcx.build.Load(llszptr.val);
+        ret call_memcpy(llszptr.bcx, dst, src, llsz);
 
     } else {
         ret res(cx, cx.build.Store(cx.build.Load(src), dst));
@@ -2182,14 +2224,17 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt,
                     auto tys = ty.resolve_ty_params(fn_item, monoty);
 
                     if (_vec.len[@ty.t](tys) != 0u) {
+                        auto bcx = cx;
                         let vec[ValueRef] tydescs = vec();
                         for (@ty.t t in tys) {
-                            append[ValueRef](tydescs,
-                                             get_tydesc(cx, t));
+                            auto td = get_tydesc(bcx, t);
+                            bcx = td.bcx;
+                            append[ValueRef](tydescs, td.val);
                         }
                         auto gen = rec( item_type = ty.item_ty(fn_item)._1,
                                         tydescs = tydescs );
-                        lv = rec(generic = some[generic_info](gen)
+                        lv = rec(res = res(bcx, lv.res.val),
+                                 generic = some[generic_info](gen)
                                  with lv);
                     }
 
@@ -2236,12 +2281,12 @@ fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base,
         case (ty.ty_tup(?fields)) {
             let uint ix = ty.field_num(cx.fcx.ccx.sess, sp, field);
             auto v = GEP_tup_like(r.bcx, t, r.val, vec(0, ix as int));
-            ret lval_mem(r.bcx, v);
+            ret lval_mem(v.bcx, v.val);
         }
         case (ty.ty_rec(?fields)) {
             let uint ix = ty.field_idx(cx.fcx.ccx.sess, sp, field, fields);
             auto v = GEP_tup_like(r.bcx, t, r.val, vec(0, ix as int));
-            ret lval_mem(r.bcx, v);
+            ret lval_mem(v.bcx, v.val);
         }
         case (ty.ty_obj(?methods)) {
             let uint ix = ty.method_idx(cx.fcx.ccx.sess, sp, field, methods);
@@ -2267,20 +2312,22 @@ fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base,
     lv = autoderef(lv.bcx, lv.val, ty.expr_ty(base));
     auto ix = trans_expr(lv.bcx, idx);
     auto v = lv.val;
+    auto bcx = ix.bcx;
 
     auto llunit_ty = node_type(cx.fcx.ccx, ann);
-    auto unit_sz = size_of(cx, node_ann_type(cx.fcx.ccx, ann));
-    auto scaled_ix = ix.bcx.build.Mul(ix.val, unit_sz);
+    auto unit_sz = size_of(bcx, node_ann_type(cx.fcx.ccx, ann));
+    bcx = unit_sz.bcx;
+    auto scaled_ix = bcx.build.Mul(ix.val, unit_sz.val);
 
-    auto lim = ix.bcx.build.GEP(v, vec(C_int(0), C_int(abi.vec_elt_fill)));
-    lim = ix.bcx.build.Load(lim);
+    auto lim = bcx.build.GEP(v, vec(C_int(0), C_int(abi.vec_elt_fill)));
+    lim = bcx.build.Load(lim);
 
-    auto bounds_check = ix.bcx.build.ICmp(lib.llvm.LLVMIntULT,
-                                          scaled_ix, lim);
+    auto bounds_check = bcx.build.ICmp(lib.llvm.LLVMIntULT,
+                                       scaled_ix, lim);
 
-    auto fail_cx = new_sub_block_ctxt(ix.bcx, "fail");
-    auto next_cx = new_sub_block_ctxt(ix.bcx, "next");
-    ix.bcx.build.CondBr(bounds_check, next_cx.llbb, fail_cx.llbb);
+    auto fail_cx = new_sub_block_ctxt(bcx, "fail");
+    auto next_cx = new_sub_block_ctxt(bcx, "next");
+    bcx.build.CondBr(bounds_check, next_cx.llbb, fail_cx.llbb);
 
     // fail: bad bounds check.
     auto fail_res = trans_fail(fail_cx, sp, "bounds check");
@@ -2590,7 +2637,8 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
                               vec(C_int(0),
                                   C_int(abi.closure_elt_tydesc)));
             auto bindings_tydesc = get_tydesc(bcx, bindings_ty);
-            bcx.build.Store(bindings_tydesc, bound_tydesc);
+            bcx = bindings_tydesc.bcx;
+            bcx.build.Store(bindings_tydesc.val, bound_tydesc);
 
             // Store thunk-target.
             auto bound_target =
@@ -2740,16 +2788,18 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args,
     }
 
     auto llunit_ty = type_of(cx.fcx.ccx, unit_ty);
-    auto unit_sz = size_of(cx, unit_ty);
+    auto bcx = cx;
+    auto unit_sz = size_of(bcx, unit_ty);
+    bcx = unit_sz.bcx;
     auto data_sz = llvm.LLVMConstMul(C_int(_vec.len[@ast.expr](args) as int),
-                                     unit_sz);
+                                     unit_sz.val);
 
     // FIXME: pass tydesc properly.
-    auto sub = trans_upcall(cx, "upcall_new_vec", vec(data_sz, C_int(0)));
+    auto sub = trans_upcall(bcx, "upcall_new_vec", vec(data_sz, C_int(0)));
 
-    auto llty = type_of(cx.fcx.ccx, t);
+    auto llty = type_of(bcx.fcx.ccx, t);
     auto vec_val = sub.bcx.build.IntToPtr(sub.val, llty);
-    find_scope_cx(cx).cleanups += clean(bind drop_ty(_, vec_val, t));
+    find_scope_cx(bcx).cleanups += clean(bind drop_ty(_, vec_val, t));
 
     auto body = sub.bcx.build.GEP(vec_val, vec(C_int(0),
                                                C_int(abi.vec_elt_data)));
@@ -3044,8 +3094,8 @@ fn init_local(@block_ctxt cx, @ast.local local) -> result {
         }
         case (_) {
             if (middle.ty.type_has_dynamic_size(ty)) {
-                auto llsz = size_of(cx, ty);
-                bcx = call_bzero(cx, llptr, llsz).bcx;
+                auto llsz = size_of(bcx, ty);
+                bcx = call_bzero(llsz.bcx, llptr, llsz.val).bcx;
 
             } else {
                 auto llty = type_of(bcx.fcx.ccx, ty);
@@ -3145,7 +3195,10 @@ fn trans_block_cleanups(@block_ctxt cx,
         check (_vec.len[cleanup](cleanup_cx.cleanups) == 0u);
     }
 
-    for (cleanup c in cleanup_cx.cleanups) {
+    auto i = _vec.len[cleanup](cleanup_cx.cleanups);
+    while (i > 0u) {
+        i -= 1u;
+        auto c = cleanup_cx.cleanups.(i);
         alt (c) {
             case (clean(?cfn)) {
                 bcx = cfn(bcx).bcx;
@@ -3176,14 +3229,16 @@ iter block_locals(&ast.block b) -> @ast.local {
 fn alloc_local(@block_ctxt cx, @ast.local local) -> result {
     auto t = node_ann_type(cx.fcx.ccx, local.ann);
     auto val = C_int(0);
+    auto bcx = cx;
     if (ty.type_has_dynamic_size(t)) {
-        auto n = size_of(cx, t);
-        val = cx.build.ArrayAlloca(T_i8(), n);
+        auto n = size_of(bcx, t);
+        bcx = n.bcx;
+        val = bcx.build.ArrayAlloca(T_i8(), n.val);
     } else {
-        val = cx.build.Alloca(type_of(cx.fcx.ccx, t));
+        val = bcx.build.Alloca(type_of(cx.fcx.ccx, t));
     }
-    cx.fcx.lllocals.insert(local.id, val);
-    ret res(cx, val);
+    bcx.fcx.lllocals.insert(local.id, val);
+    ret res(bcx, val);
 }
 
 fn trans_block(@block_ctxt cx, &ast.block b) -> result {
@@ -3523,43 +3578,45 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid,
 
         // Malloc a box for the body.
         auto r = trans_malloc_inner(bcx, llobj_body_ty);
+        bcx = r.bcx;
         auto box = r.val;
-        auto rc = r.bcx.build.GEP(box,
+        auto rc = bcx.build.GEP(box,
+                                vec(C_int(0),
+                                    C_int(abi.box_rc_field_refcnt)));
+        auto body = bcx.build.GEP(box,
                                   vec(C_int(0),
-                                      C_int(abi.box_rc_field_refcnt)));
-        auto body = r.bcx.build.GEP(box,
-                                    vec(C_int(0),
-                                        C_int(abi.box_rc_field_body)));
-        r.bcx.build.Store(C_int(1), rc);
+                                      C_int(abi.box_rc_field_body)));
+        bcx.build.Store(C_int(1), rc);
 
         // Store body tydesc.
         auto body_tydesc =
-            r.bcx.build.GEP(body,
-                            vec(C_int(0),
-                                C_int(abi.obj_body_elt_tydesc)));
+            bcx.build.GEP(body,
+                          vec(C_int(0),
+                              C_int(abi.obj_body_elt_tydesc)));
 
         auto fields_tydesc = get_tydesc(r.bcx, fields_ty);
-        r.bcx.build.Store(fields_tydesc, body_tydesc);
+        bcx = fields_tydesc.bcx;
+        bcx.build.Store(fields_tydesc.val, body_tydesc);
 
         // Copy args into body fields.
         auto body_fields =
-            r.bcx.build.GEP(body,
-                            vec(C_int(0),
-                                C_int(abi.obj_body_elt_fields)));
+            bcx.build.GEP(body,
+                          vec(C_int(0),
+                              C_int(abi.obj_body_elt_fields)));
 
         let int i = 0;
         for (ast.obj_field f in ob.fields) {
-            auto arg = r.bcx.fcx.llargs.get(f.id);
-            arg = load_scalar_or_boxed(r.bcx, arg, arg_tys.(i).ty);
-            auto field = r.bcx.build.GEP(body_fields,
+            auto arg = bcx.fcx.llargs.get(f.id);
+            arg = load_scalar_or_boxed(bcx, arg, arg_tys.(i).ty);
+            auto field = bcx.build.GEP(body_fields,
                                          vec(C_int(0),C_int(i)));
-            r = copy_ty(r.bcx, INIT, field, arg, arg_tys.(i).ty);
+            bcx = copy_ty(bcx, INIT, field, arg, arg_tys.(i).ty).bcx;
             i += 1;
         }
 
         // Store box ptr in outer pair.
-        auto p = r.bcx.build.PointerCast(box, llbox_ty);
-        r.bcx.build.Store(p, pair_box);
+        auto p = bcx.build.PointerCast(box, llbox_ty);
+        bcx.build.Store(p, pair_box);
     }
     bcx.build.Ret(bcx.build.Load(pair));
 }
@@ -3980,13 +4037,9 @@ fn create_typedefs(@crate_ctxt cx) {
     llvm.LLVMAddTypeName(cx.llmod, _str.buf("rust_tydesc"), T_tydesc());
 }
 
-fn crate_constant(@crate_ctxt cx) -> ValueRef {
-
-    let ValueRef crate_ptr =
-        llvm.LLVMAddGlobal(cx.llmod, T_crate(),
-                           _str.buf("rust_crate"));
+fn create_crate_constant(@crate_ctxt cx) {
 
-    let ValueRef crate_addr = p2i(crate_ptr);
+    let ValueRef crate_addr = p2i(cx.crate_ptr);
 
     let ValueRef activate_glue_off =
         llvm.LLVMConstSub(p2i(cx.glues.activate_glue), crate_addr);
@@ -3999,7 +4052,7 @@ fn crate_constant(@crate_ctxt cx) -> ValueRef {
 
     let ValueRef crate_val =
         C_struct(vec(C_null(T_int()),     // ptrdiff_t image_base_off
-                     p2i(crate_ptr),      // uintptr_t self_addr
+                     p2i(cx.crate_ptr),   // uintptr_t self_addr
                      C_null(T_int()),     // ptrdiff_t debug_abbrev_off
                      C_null(T_int()),     // size_t debug_abbrev_sz
                      C_null(T_int()),     // ptrdiff_t debug_info_off
@@ -4014,8 +4067,7 @@ fn crate_constant(@crate_ctxt cx) -> ValueRef {
                      C_null(T_int())      // int n_libs
                      ));
 
-    llvm.LLVMSetInitializer(crate_ptr, crate_val);
-    ret crate_ptr;
+    llvm.LLVMSetInitializer(cx.crate_ptr, crate_val);
 }
 
 fn trans_main_fn(@crate_ctxt cx, ValueRef llcrate) {
@@ -4204,6 +4256,8 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
     llvm.LLVMSetDataLayout(llmod, _str.buf(x86.get_data_layout()));
     llvm.LLVMSetTarget(llmod, _str.buf(x86.get_target_triple()));
     auto td = mk_target_data(x86.get_data_layout());
+    let ValueRef crate_ptr =
+        llvm.LLVMAddGlobal(llmod, T_crate(), _str.buf("rust_crate"));
 
     llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm()));
 
@@ -4218,6 +4272,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
     auto cx = @rec(sess = sess,
                    llmod = llmod,
                    td = td,
+                   crate_ptr = crate_ptr,
                    upcalls = new_str_hash[ValueRef](),
                    intrinsics = intrinsics,
                    item_names = new_str_hash[ValueRef](),
@@ -4242,8 +4297,9 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
 
     trans_mod(cx, crate.node.module);
     trans_exit_task_glue(cx);
+    create_crate_constant(cx);
     if (!shared) {
-        trans_main_fn(cx, crate_constant(cx));
+        trans_main_fn(cx, cx.crate_ptr);
     }
 
     check_module(llmod);
diff --git a/src/test/compile-fail/infinite-vec-type-recursion.rs b/src/test/compile-fail/infinite-vec-type-recursion.rs
index 7c82700accb..9315488b056 100644
--- a/src/test/compile-fail/infinite-vec-type-recursion.rs
+++ b/src/test/compile-fail/infinite-vec-type-recursion.rs
@@ -1,6 +1,6 @@
 // -*- rust -*-
 
-// error-pattern: Infinite type recursion
+// error-pattern: infinite recursive type definition
 
 type x = vec[x];
 
diff --git a/src/test/run-pass/many.rs b/src/test/run-pass/many.rs
index e300312c497..2c3d642523e 100644
--- a/src/test/run-pass/many.rs
+++ b/src/test/run-pass/many.rs
@@ -1,6 +1,6 @@
 // -*- rust -*-
 
-io fn sub(chan[int] parent, int id) {
+impure fn sub(chan[int] parent, int id) {
   if (id == 0) {
     parent <| 0;
   } else {
@@ -11,7 +11,7 @@ io fn sub(chan[int] parent, int id) {
   }
 }
 
-io fn main() {
+impure fn main() {
   let port[int] p = port();
   auto child = spawn sub(chan(p), 500);
   let int y <- p;
diff --git a/src/test/run-pass/task-comm-10.rs b/src/test/run-pass/task-comm-10.rs
index 4cdcf18b9ce..e0164596390 100644
--- a/src/test/run-pass/task-comm-10.rs
+++ b/src/test/run-pass/task-comm-10.rs
@@ -1,11 +1,11 @@
-io fn start(chan[chan[str]] c) {
+impure fn start(chan[chan[str]] c) {
     let port[str] p = port();
     c <| chan(p);
     auto a <- p;
     // auto b <- p; // Never read the second string.
 }
 
-io fn main() {
+impure fn main() {
     let port[chan[str]] p = port();
     auto child = spawn "start" start(chan(p));
     auto c <- p;
diff --git a/src/test/run-pass/task-comm-15.rs b/src/test/run-pass/task-comm-15.rs
index 70680e248ba..b5bd733144c 100644
--- a/src/test/run-pass/task-comm-15.rs
+++ b/src/test/run-pass/task-comm-15.rs
@@ -1,4 +1,4 @@
-io fn start(chan[int] c, int n) {
+impure fn start(chan[int] c, int n) {
     let int i = n;
 
     while(i > 0) {
@@ -7,7 +7,7 @@ io fn start(chan[int] c, int n) {
     }
 }
 
-io fn main() {
+impure fn main() {
     let port[int] p = port();
     // Spawn a task that sends us back messages. The parent task
     // is likely to terminate before the child completes, so from
diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs
index 9a3f9e16919..d833c3a5810 100644
--- a/src/test/run-pass/task-comm-3.rs
+++ b/src/test/run-pass/task-comm-3.rs
@@ -1,11 +1,11 @@
-io fn main() -> () {
+impure fn main() -> () {
    log "===== WITHOUT THREADS =====";
    test00(false);
    log "====== WITH THREADS ======";
    test00(true);
 }
 
-io fn test00_start(chan[int] ch, int message, int count) {
+impure fn test00_start(chan[int] ch, int message, int count) {
     log "Starting test00_start";
     let int i = 0;
     while (i < count) {
@@ -16,7 +16,7 @@ io fn test00_start(chan[int] ch, int message, int count) {
     log "Ending test00_start";
 }
 
-io fn test00(bool is_multithreaded) {
+impure fn test00(bool is_multithreaded) {
     let int number_of_tasks = 16;
     let int number_of_messages = 4;
     
diff --git a/src/test/run-pass/task-comm-8.rs b/src/test/run-pass/task-comm-8.rs
index c5f73a3f08e..87fa3d89548 100644
--- a/src/test/run-pass/task-comm-8.rs
+++ b/src/test/run-pass/task-comm-8.rs
@@ -1,8 +1,8 @@
-io fn main() -> () {
+impure fn main() -> () {
    test00();
 }
 
-io fn test00_start(chan[int] c, int start, int number_of_messages) {
+impure fn test00_start(chan[int] c, int start, int number_of_messages) {
     let int i = 0;
     while (i < number_of_messages) {
         c <| start + i;
@@ -10,7 +10,7 @@ io fn test00_start(chan[int] c, int start, int number_of_messages) {
     }    
 }
 
-io fn test00() {
+impure fn test00() {
     let int r = 0;    
     let int sum = 0;
     let port[int] p = port();
diff --git a/src/test/run-pass/task-comm-9.rs b/src/test/run-pass/task-comm-9.rs
index a2c9d5c9b4c..370a36e34b8 100644
--- a/src/test/run-pass/task-comm-9.rs
+++ b/src/test/run-pass/task-comm-9.rs
@@ -1,8 +1,8 @@
-io fn main() -> () {
+impure fn main() -> () {
    test00();
 }
 
-io fn test00_start(chan[int] c, int number_of_messages) {
+impure fn test00_start(chan[int] c, int number_of_messages) {
     let int i = 0;
     while (i < number_of_messages) {
         c <| i;
@@ -10,7 +10,7 @@ io fn test00_start(chan[int] c, int number_of_messages) {
     }    
 }
 
-io fn test00() {
+impure fn test00() {
     let int r = 0;    
     let int sum = 0;
     let port[int] p = port();
diff --git a/src/test/run-pass/task-comm.rs b/src/test/run-pass/task-comm.rs
index 3c5d321689f..d5f9a3a0dae 100644
--- a/src/test/run-pass/task-comm.rs
+++ b/src/test/run-pass/task-comm.rs
@@ -1,5 +1,5 @@
 
-io fn main() -> () {
+impure fn main() -> () {
     test00(true);
     // test01();
     test02();
@@ -9,7 +9,7 @@ io fn main() -> () {
     test06();
 }
 
-io fn test00_start(chan[int] ch, int message, int count) {
+impure fn test00_start(chan[int] ch, int message, int count) {
     log "Starting test00_start";
     let int i = 0;
     while (i < count) {
@@ -20,7 +20,7 @@ io fn test00_start(chan[int] ch, int message, int count) {
     log "Ending test00_start";
 }
 
-io fn test00(bool is_multithreaded) {
+impure fn test00(bool is_multithreaded) {
     let int number_of_tasks = 1;
     let int number_of_messages = 4;
     log "Creating tasks";
@@ -60,14 +60,14 @@ io fn test00(bool is_multithreaded) {
            (number_of_tasks * number_of_tasks + number_of_tasks) / 2);
 }
 
-io fn test01() {
+impure fn test01() {
     let port[int] p = port();
     log "Reading from a port that is never written to.";
     let int value <- p;
     log value;
 }
 
-io fn test02() {
+impure fn test02() {
     let port[int] p = port();
     let chan[int] c = chan(p);
     log "Writing to a local task channel.";
@@ -111,7 +111,7 @@ fn test04() {
     log "Finishing up.";
 }
 
-io fn test05_start(chan[int] ch) {
+impure fn test05_start(chan[int] ch) {
     ch <| 10;
     ch <| 20;
     ch <| 30;
@@ -119,7 +119,7 @@ io fn test05_start(chan[int] ch) {
     ch <| 30;    
 }
 
-io fn test05() {
+impure fn test05() {
     let port[int] po = port();
     let chan[int] ch = chan(po);
     spawn thread test05_start(ch);