about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLindsey Kuper <lkuper@mozilla.com>2011-05-27 17:58:22 -0700
committerLindsey Kuper <lkuper@mozilla.com>2011-05-27 18:20:43 -0700
commitdc9d5e168977b9f3e2595b2c33aaf4c90f09ae81 (patch)
tree5d68f17a708dbd329937bb36b6e0bbf761ede7e9
parentb6e0c5829f5bb87b9a3f0f74b1d98f6ea4cc8cef (diff)
downloadrust-dc9d5e168977b9f3e2595b2c33aaf4c90f09ae81.tar.gz
rust-dc9d5e168977b9f3e2595b2c33aaf4c90f09ae81.zip
Lots of comments, and some more descriptive names.
-rw-r--r--src/comp/lib/llvm.rs8
-rw-r--r--src/comp/middle/trans.rs257
2 files changed, 209 insertions, 56 deletions
diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs
index 35a1d990ab4..0de35b9f006 100644
--- a/src/comp/lib/llvm.rs
+++ b/src/comp/lib/llvm.rs
@@ -886,7 +886,13 @@ native mod llvm = llvm_lib {
 native mod rustllvm = llvm_lib {
 }
 
-/* Slightly more terse object-interface to LLVM's 'builder' functions. */
+/* Slightly more terse object-interface to LLVM's 'builder' functions. For the
+ * most part, build.Foo() wraps LLVMBuildFoo(), threading the correct
+ * BuilderRef B into place.  A BuilderRef is a cursor-like LLVM value that
+ * inserts instructions for a particular BasicBlockRef at a particular
+ * position; for our purposes, it always inserts at the end of the basic block
+ * it's attached to.  
+ */
 
 // FIXME: Do we want to support mutable object fields?
 obj builder(BuilderRef B, @mutable bool terminated) {
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 5cb14879253..9fe5d70bf71 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -129,44 +129,155 @@ type local_ctxt = rec(vec[str] path,
                       @crate_ctxt ccx);
 
 
+// The type used for llself.
 type self_vt = rec(ValueRef v, ty::t t);
 
-state type fn_ctxt = rec(ValueRef llfn,
-                         ValueRef lltaskptr,
-                         ValueRef llenv,
-                         ValueRef llretptr,
-                         mutable BasicBlockRef llallocas,
-                         mutable BasicBlockRef llcopyargs,
-                         mutable BasicBlockRef llderivedtydescs,
-                         mutable option::t[self_vt] llself,
-                         mutable option::t[ValueRef] lliterbody,
-                         hashmap[ast::def_id, ValueRef] llargs,
-                         hashmap[ast::def_id, ValueRef] llobjfields,
-                         hashmap[ast::def_id, ValueRef] lllocals,
-                         hashmap[ast::def_id, ValueRef] llupvars,
-                         mutable vec[ValueRef] lltydescs,
-                         hashmap[ty::t, derived_tydesc_info] derived_tydescs,
-                         ast::span sp,
-                         @local_ctxt lcx);
+// Function context.  Every LLVM function we create will have one of these.
+state type fn_ctxt = rec(
+    // The ValueRef returned from a call to llvm::LLVMAddFunction; the address
+    // of the first instruction in the sequence of instructions for this
+    // function that will go in the .text section of the executable we're
+    // generating.
+    ValueRef llfn,
+
+    // The three implicit arguments that arrive in the function we're
+    // creating.  For instance, foo(int, int) is really foo(ret*, task*, env*,
+    // int, int).  These are also available via llvm::LLVMGetParam(llfn, uint)
+    // where uint = 2, 0, 1 respectively, but we unpack them here for
+    // convenience.
+    ValueRef lltaskptr,
+    ValueRef llenv,
+    ValueRef llretptr,
+    
+    // The next three elements: "hoisted basic blocks" containing
+    // administrative activities that have to happen in only one place in the
+    // function, due to LLVM's quirks.
+
+    // A block for all the function's allocas, so that LLVM will coalesce them
+    // into a single alloca.
+    mutable BasicBlockRef llallocas, 
+
+    // A block containing code that copies incoming arguments to space already
+    // allocated by code in the llallocas block.  (LLVM requires that
+    // arguments be copied to local allocas before allowing most any operation
+    // to be performed on them.)
+    mutable BasicBlockRef llcopyargs,
+
+    // A block containing derived tydescs received from the runtime.  See
+    // description of derived_tydescs, below.
+    mutable BasicBlockRef llderivedtydescs,
+
+    // FIXME: Is llcopyargs actually the block containing the allocas for
+    // incoming function arguments?  Or is it merely the block containing code
+    // that copies incoming args to space already alloca'd by code in
+    // llallocas?
+
+    // The 'self' object currently in use in this function, if there is one.
+    mutable option::t[self_vt] llself,
+
+    // If this function is actually a iter, a block containing the code called
+    // whenever the iter calls 'put'.
+    mutable option::t[ValueRef] lliterbody,
+
+    // The next four items: hash tables mapping from AST def_ids to
+    // LLVM-stuff-in-the-frame.
+
+    // Maps arguments to allocas created for them in llallocas.
+    hashmap[ast::def_id, ValueRef] llargs,
+
+    // Maps fields in objects to pointers into the interior of llself's body.
+    hashmap[ast::def_id, ValueRef] llobjfields,
+
+    // Maps the def_ids for local variables to the allocas created for them in
+    // llallocas.
+    hashmap[ast::def_id, ValueRef] lllocals,
+
+    // The same as above, but for variables accessed via the frame pointer we
+    // pass into an iter, for access to the static environment of the
+    // iter-calling frame.
+    hashmap[ast::def_id, ValueRef] llupvars,
+
+    // For convenience, a vector of the incoming tydescs for each of this
+    // functions type parameters, fetched via llvm::LLVMGetParam.  For
+    // example, for a function foo[A, B, C](), lltydescs contains the
+    // ValueRefs for the tydescs for A, B, and C.
+    mutable vec[ValueRef] lltydescs,
+
+    // Derived tydescs are tydescs created at runtime, for types that involve
+    // type parameters inside type constructors.  For example, suppose a
+    // function parameterized by T creates a vector of type vec[T].  The
+    // function doesn't know what T is until runtime, and the function's
+    // caller knows T but doesn't know that a vector is involved.  So a tydesc
+    // for vec[T] can't be created until runtime, when information about both
+    // "vec" and "T" are available.  When such a tydesc is created, we cache
+    // it in the derived_tydescs table for the next time that such a tydesc is
+    // needed.
+    hashmap[ty::t, derived_tydesc_info] derived_tydescs,
+
+    // The source span where this function comes from, for error reporting.
+    ast::span sp,
+
+    // This function's enclosing local context.
+    @local_ctxt lcx
+    );
 
 tag cleanup {
     clean(fn(&@block_ctxt cx) -> result);
 }
 
-
 tag block_kind {
+    // A scope block is a basic block created by translating a block { ... }
+    // the the source language.  Since these blocks create variable scope, any
+    // variables created in them that are still live at the end of the block
+    // must be dropped and cleaned up when the block ends.
     SCOPE_BLOCK;
+
+    // A basic block created from the body of a loop.  Contains pointers to
+    // which block to jump to in the case of "continue" or "break", with the
+    // "continue" block optional, because "while" and "do while" don't support
+    // "continue" (TODO: is this intentional?)
     LOOP_SCOPE_BLOCK(option::t[@block_ctxt], @block_ctxt);
+
+    // A non-scope block is a basic block created as a translation artifact
+    // from translating code that expresses conditional logic rather than by
+    // explicit { ... } block structure in the source language.  It's called a
+    // non-scope block because it doesn't introduce a new variable scope.
     NON_SCOPE_BLOCK;
 }
 
-state type block_ctxt = rec(BasicBlockRef llbb,
-                            builder build,
-                            block_parent parent,
-                            block_kind kind,
-                            mutable vec[cleanup] cleanups,
-                            ast::span sp,
-                            @fn_ctxt fcx);
+// Basic block context.  We create a block context for each basic block
+// (single-entry, single-exit sequence of instructions) we generate from Rust
+// code.  Each basic block we generate is attached to a function, typically
+// with many basic blocks per function.  All the basic blocks attached to a
+// function are organized as a directed graph.
+state type block_ctxt = rec(
+    // The BasicBlockRef returned from a call to
+    // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic block to the
+    // function pointed to by llfn.  We insert instructions into that block by
+    // way of this block context.
+    BasicBlockRef llbb,
+
+    // The llvm::builder object serving as an interface to LLVM's LLVMBuild*
+    // functions.
+    builder build,
+
+    // The block pointing to this one in the function's digraph.
+    block_parent parent,
+
+    // The 'kind' of basic block this is.
+    block_kind kind,
+
+    // A list of functions that run at the end of translating this block,
+    // cleaning up any variables that were introduced in the block and need to
+    // go out of scope at the end of it.
+    mutable vec[cleanup] cleanups,
+
+    // The source span where this block comes from, for error reporting.
+    ast::span sp,
+
+    // The function context for the function to which this block is attached.
+    @fn_ctxt fcx
+    );
 
 // FIXME: we should be able to use option::t[@block_parent] here but
 // the infinite-tag check in rustboot gets upset.
@@ -3115,7 +3226,7 @@ tag copy_action {
     DROP_EXISTING;
 }
 
-fn copy_ty(&@block_ctxt cx,
+fn copy_val(&@block_ctxt cx,
            copy_action action,
            ValueRef dst,
            ValueRef src,
@@ -3143,7 +3254,7 @@ fn copy_ty(&@block_ctxt cx,
         ret memmove_ty(r.bcx, dst, src, t);
     }
 
-    cx.fcx.lcx.ccx.sess.bug("unexpected type in trans::copy_ty: " +
+    cx.fcx.lcx.ccx.sess.bug("unexpected type in trans::copy_val: " +
                         ty::ty_to_str(cx.fcx.lcx.ccx.tcx, t));
     fail;
 }
@@ -3263,7 +3374,7 @@ fn trans_unary(&@block_ctxt cx, ast::unop op,
                 body = sub.bcx.build.PointerCast(body, llety);
             }
 
-            sub = copy_ty(sub.bcx, INIT, body, e_val, e_ty);
+            sub = copy_val(sub.bcx, INIT, body, e_val, e_ty);
             ret res(sub.bcx, box);
         }
         case (ast::deref) {
@@ -3353,7 +3464,7 @@ fn trans_vec_add(&@block_ctxt cx, &ty::t t,
                  ValueRef lhs, ValueRef rhs) -> result {
     auto r = alloc_ty(cx, t);
     auto tmp = r.val;
-    r = copy_ty(r.bcx, INIT, tmp, lhs, t);
+    r = copy_val(r.bcx, INIT, tmp, lhs, t);
     auto bcx = trans_vec_append(r.bcx, t, tmp, rhs).bcx;
     tmp = load_if_immediate(bcx, tmp, t);
     find_scope_cx(cx).cleanups +=
@@ -3681,7 +3792,7 @@ fn trans_for(&@block_ctxt cx,
 
         cx.build.Br(scope_cx.llbb);
         auto local_res = alloc_local(scope_cx, local);
-        auto bcx = copy_ty(local_res.bcx, INIT, local_res.val, curr, t).bcx;
+        auto bcx = copy_val(local_res.bcx, INIT, local_res.val, curr, t).bcx;
         scope_cx.cleanups +=
             [clean(bind drop_slot(_, local_res.val, t))];
         bcx = trans_block(bcx, body).bcx;
@@ -4113,7 +4224,7 @@ fn trans_pat_binding(&@block_ctxt cx, &@ast::pat pat,
                 bcx.fcx.lllocals.insert(def_id, dst);
                 bcx.cleanups +=
                     [clean(bind drop_slot(_, dst, t))];
-                ret copy_ty(bcx, INIT, dst, llval, t);
+                ret copy_val(bcx, INIT, dst, llval, t);
             }
         }
         case (ast::pat_tag(_, ?subpats, ?ann)) {
@@ -4846,7 +4957,7 @@ fn trans_bind(&@block_ctxt cx, &@ast::expr f,
             for (ValueRef v in bound_vals) {
                 auto bound = bcx.build.GEP(bindings,
                                            [C_int(0), C_int(i as int)]);
-                bcx = copy_ty(bcx, INIT, bound, v, bound_tys.(i)).bcx;
+                bcx = copy_val(bcx, INIT, bound, v, bound_tys.(i)).bcx;
                 i += 1u;
             }
 
@@ -5180,7 +5291,7 @@ fn trans_tup(&@block_ctxt cx, &vec[ast::elt] elts,
         bcx = src_res.bcx;
         auto dst_res = GEP_tup_like(bcx, t, tup_val, [0, i]);
         bcx = dst_res.bcx;
-        bcx = copy_ty(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty).bcx;
+        bcx = copy_val(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty).bcx;
         i += 1;
     }
     ret res(bcx, tup_val);
@@ -5250,7 +5361,7 @@ fn trans_vec(&@block_ctxt cx, &vec[@ast::expr] args,
             dst_val = dst_res.val;
         }
 
-        bcx = copy_ty(bcx, INIT, dst_val, src_res.val, unit_ty).bcx;
+        bcx = copy_val(bcx, INIT, dst_val, src_res.val, unit_ty).bcx;
         i += 1;
     }
     auto fill = bcx.build.GEP(vec_val,
@@ -5310,7 +5421,7 @@ fn trans_rec(&@block_ctxt cx, &vec[ast::field] fields,
         }
 
         bcx = src_res.bcx;
-        bcx = copy_ty(bcx, INIT, dst_res.val, src_res.val, e_ty).bcx;
+        bcx = copy_val(bcx, INIT, dst_res.val, src_res.val, e_ty).bcx;
         i += 1;
     }
     ret res(bcx, rec_val);
@@ -5376,7 +5487,7 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result {
             auto rhs_res = trans_expr(lhs_res.res.bcx, src);
             auto t = node_ann_type(cx.fcx.lcx.ccx, ann);
             // FIXME: calculate copy init-ness in typestate.
-            ret copy_ty(rhs_res.bcx, DROP_EXISTING,
+            ret copy_val(rhs_res.bcx, DROP_EXISTING,
                         lhs_res.res.val, rhs_res.val, t);
         }
 
@@ -5401,7 +5512,7 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result {
             auto v = trans_eager_binop(rhs_res.bcx, op, t,
                                        lhs_val, rhs_res.val);
             // FIXME: calculate copy init-ness in typestate.
-            ret copy_ty(v.bcx, DROP_EXISTING,
+            ret copy_val(v.bcx, DROP_EXISTING,
                         lhs_res.res.val, v.val, t);
         }
 
@@ -5752,7 +5863,7 @@ fn trans_ret(&@block_ctxt cx, &option::t[@ast::expr] e) -> result {
             auto r = trans_expr(cx, x);
             bcx = r.bcx;
             val = r.val;
-            bcx = copy_ty(bcx, INIT, cx.fcx.llretptr, val, t).bcx;
+            bcx = copy_val(bcx, INIT, cx.fcx.llretptr, val, t).bcx;
         }
         case (_) {
             auto t = llvm::LLVMGetElementType(val_ty(cx.fcx.llretptr));
@@ -6029,7 +6140,7 @@ fn trans_send(&@block_ctxt cx, &@ast::expr lhs, &@ast::expr rhs,
 
     auto data_alloc = alloc_ty(bcx, unit_ty);
     bcx = data_alloc.bcx;
-    auto data_tmp = copy_ty(bcx, INIT, data_alloc.val, data.val, unit_ty);
+    auto data_tmp = copy_val(bcx, INIT, data_alloc.val, data.val, unit_ty);
     bcx = data_tmp.bcx;
 
     find_scope_cx(bcx).cleanups +=
@@ -6069,7 +6180,7 @@ fn recv_val(&@block_ctxt cx, ValueRef lhs, &@ast::expr rhs,
                    [bcx.fcx.lltaskptr, lldataptr, llportptr]);
 
     auto data_load = load_if_immediate(bcx, lhs, unit_ty);
-    auto cp = copy_ty(bcx, action, lhs, data_load, unit_ty);
+    auto cp = copy_val(bcx, action, lhs, data_load, unit_ty);
     bcx = cp.bcx;
 
     // TODO: Any cleanup need to be done here?
@@ -6119,9 +6230,9 @@ fn trans_anon_obj(&@block_ctxt cx, &ast::span sp,
     alt (anon_obj.with_obj) {
         case (none[@ast::expr]) { }
         case (some[@ast::expr](?e)) {
-            // Translating with_obj returns a pointer to a 2-word value.  We
-            // want to allocate space for this value in our outer object, then
-            // copy it into the outer object.
+            // Translating with_obj returns a ValueRef (pointer to a 2-word
+            // value) wrapped in a result.  We want to allocate space for this
+            // value in our outer object, then copy it into the outer object.
             with_obj_val = some[result](trans_expr(cx, e));
         }
     }
@@ -6164,7 +6275,7 @@ fn init_local(&@block_ctxt cx, &@ast::local local) -> result {
             alt (init.op) {
                 case (ast::init_assign) {
                     auto sub = trans_expr(bcx, init.expr);
-                    bcx = copy_ty(sub.bcx, INIT, llptr, sub.val, ty).bcx;
+                    bcx = copy_val(sub.bcx, INIT, llptr, sub.val, ty).bcx;
                 }
                 case (ast::init_recv) {
                     bcx = recv_val(bcx, llptr, init.expr, ty, INIT).bcx;
@@ -6273,7 +6384,13 @@ fn new_raw_block_ctxt(&@fn_ctxt fcx, BasicBlockRef llbb) -> @block_ctxt {
              fcx=fcx);
 }
 
-
+// trans_block_cleanups: Go through all the cleanups attached to this
+// block_ctxt and execute them.  
+//
+// When translating a block that introdces new variables during its scope, we
+// need to make sure those variables go out of scope when the block ends.  We
+// do that by running a 'cleanup' function for each variable.
+// trans_block_cleanups runs all the cleanup functions for the block.
 fn trans_block_cleanups(&@block_ctxt cx,
                         &@block_ctxt cleanup_cx) -> @block_ctxt {
     auto bcx = cx;
@@ -6407,7 +6524,7 @@ fn trans_block(&@block_ctxt cx, &ast::block b) -> result {
                     zero_alloca(llbcx, res_alloca.val, r_ty);
 
                     // Now we're working in our own block context again
-                    auto res_copy = copy_ty(bcx, INIT,
+                    auto res_copy = copy_val(bcx, INIT,
                                             res_alloca.val, r.val, r_ty);
                     bcx = res_copy.bcx;
 
@@ -6713,6 +6830,8 @@ fn finish_fn(&@fn_ctxt fcx, BasicBlockRef lltop) {
     new_builder(fcx.llderivedtydescs).Br(lltop);
 }
 
+// trans_fn: creates an LLVM function corresponding to a source language
+// function.
 fn trans_fn(@local_ctxt cx, &ast::span sp, &ast::_fn f, ast::def_id fid,
             option::t[tup(TypeRef, ty::t)] ty_self,
             &vec[ast::ty_param] ty_params, &ast::ann ann) {
@@ -6751,7 +6870,7 @@ fn trans_fn(@local_ctxt cx, &ast::span sp, &ast::_fn f, ast::def_id fid,
     finish_fn(fcx, lltop);
 }
 
-fn trans_vtbl(@local_ctxt cx,
+fn create_vtbl(@local_ctxt cx,
               TypeRef llself_ty,
               ty::t self_ty,
               &ast::_obj ob,
@@ -6828,11 +6947,21 @@ fn trans_dtor(@local_ctxt cx,
     ret llfn;
 }
 
+// trans_obj: creates an LLVM function that is the object constructor for the
+// object being translated.
 fn trans_obj(@local_ctxt cx, &ast::span sp, &ast::_obj ob, ast::def_id oid,
              &vec[ast::ty_param] ty_params, &ast::ann ann) {
+    // To make a function, we have to create a function context and, inside
+    // that, a number of block contexts for which code is generated.
+
     auto ccx = cx.ccx;
+
     auto llctor_decl = ccx.item_ids.get(oid);
 
+    // Much like trans_fn, we must create an LLVM function, but since we're
+    // starting with an ast::_obj rather than an ast::_fn, we have some setup
+    // work to do.
+
     // Translate obj ctor args to function arguments.
     let vec[ast::arg] fn_args = [];
     for (ast::obj_field f in ob.fields) {
@@ -6848,6 +6977,8 @@ fn trans_obj(@local_ctxt cx, &ast::span sp, &ast::_obj ob, ast::def_id oid,
     let vec[ty::arg] arg_tys = arg_tys_of_fn(ccx, ann);
     copy_args_to_allocas(fcx, fn_args, arg_tys);
 
+    //  Make the first block context in the function and keep a handle on it
+    //  to pass to finish_fn later.
     auto bcx = new_top_block_ctxt(fcx);
     auto lltop = bcx.llbb;
 
@@ -6855,7 +6986,8 @@ fn trans_obj(@local_ctxt cx, &ast::span sp, &ast::_obj ob, ast::def_id oid,
     auto llself_ty = type_of(ccx, sp, self_ty);
     auto pair = bcx.fcx.llretptr;
 
-    auto vtbl = trans_vtbl(cx, llself_ty, self_ty, ob, ty_params);
+    auto vtbl = create_vtbl(cx, llself_ty, self_ty, ob, ty_params);
+
     auto pair_vtbl = bcx.build.GEP(pair,
                                    [C_int(0),
                                        C_int(abi::obj_field_vtbl)]);
@@ -6874,6 +7006,7 @@ fn trans_obj(@local_ctxt cx, &ast::span sp, &ast::_obj ob, ast::def_id oid,
         bcx.build.Store(C_null(llbox_ty), pair_box);
     } else {
         // Malloc a box for the body and copy args in.
+
         let vec[ty::t] obj_fields = [];
         for (ty::arg a in arg_tys) {
             vec::push[ty::t](obj_fields, a.ty);
@@ -6886,12 +7019,19 @@ fn trans_obj(@local_ctxt cx, &ast::span sp, &ast::_obj ob, ast::def_id oid,
             vec::push[ty::t](tps, tydesc_ty);
         }
 
+        // typarams_ty = [typaram_ty, ...]
         let ty::t typarams_ty = ty::mk_imm_tup(ccx.tcx, tps);
-        let ty::t fields_ty = ty::mk_imm_tup(ccx.tcx, obj_fields);
+
+        // fields_ty = [field_ty, ...]
+        let ty::t fields_ty = ty::mk_imm_tup(ccx.tcx, obj_fields); 
+
+        // body_ty = [tydesc_ty, [typaram_ty, ...], [field_ty, ...]]
         let ty::t body_ty = ty::mk_imm_tup(ccx.tcx,
                                           [tydesc_ty,
-                                              typarams_ty,
-                                              fields_ty]);
+                                           typarams_ty,
+                                           fields_ty]);
+
+        // boxed_body_ty = [[tydesc_ty, [typaram_ty, ...], [field_ty, ...]]]
         let ty::t boxed_body_ty = ty::mk_imm_box(ccx.tcx, body_ty);
 
         // Malloc a box for the body.
@@ -6900,12 +7040,19 @@ fn trans_obj(@local_ctxt cx, &ast::span sp, &ast::_obj ob, ast::def_id oid,
         auto rc = GEP_tup_like(bcx, boxed_body_ty, box.val,
                                [0, abi::box_rc_field_refcnt]);
         bcx = rc.bcx;
+
+        // We've now created a structure that looks like:
+        // [refcount, [tydesc_ty, [typaram_ty, ...], [field_ty, ...]]]
+
         auto body = GEP_tup_like(bcx, boxed_body_ty, box.val,
                                  [0, abi::box_rc_field_body]);
         bcx = body.bcx;
+
+
         bcx.build.Store(C_int(1), rc.val);
 
-        // Store body tydesc.
+        // Put together a tydesc for the body, so that the object can later be
+        // freed by calling through its tydesc.
         auto body_tydesc =
             GEP_tup_like(bcx, body_ty, body.val,
                          [0, abi::obj_body_elt_tydesc]);
@@ -6938,7 +7085,7 @@ fn trans_obj(@local_ctxt cx, &ast::span sp, &ast::_obj ob, ast::def_id oid,
             auto capture = GEP_tup_like(bcx, typarams_ty, body_typarams.val,
                                         [0, i]);
             bcx = capture.bcx;
-            bcx = copy_ty(bcx, INIT, capture.val, typaram, tydesc_ty).bcx;
+            bcx = copy_val(bcx, INIT, capture.val, typaram, tydesc_ty).bcx;
             i += 1;
         }
 
@@ -6955,7 +7102,7 @@ fn trans_obj(@local_ctxt cx, &ast::span sp, &ast::_obj ob, ast::def_id oid,
             auto field = GEP_tup_like(bcx, fields_ty, body_fields.val,
                                       [0, i]);
             bcx = field.bcx;
-            bcx = copy_ty(bcx, INIT, field.val, arg, arg_tys.(i).ty).bcx;
+            bcx = copy_val(bcx, INIT, field.val, arg, arg_tys.(i).ty).bcx;
             i += 1;
         }
         // Store box ptr in outer pair.
@@ -7040,7 +7187,7 @@ fn trans_tag_variant(@local_ctxt cx, ast::def_id tag_id,
             llargval = bcx.build.Load(llargptr);
         }
 
-        rslt = copy_ty(bcx, INIT, lldestptr, llargval, arg_ty);
+        rslt = copy_val(bcx, INIT, lldestptr, llargval, arg_ty);
         bcx = rslt.bcx;
 
         i += 1u;