+fn make_opaque_cbox_take_glue(
+ bcx: @block_ctxt,
+ ck: ty::closure_kind,
+ cboxptr: ValueRef) // ptr to ptr to the opaque closure
+ -> @block_ctxt {
+ // Easy cases:
+ alt ck {
+ ty::closure_block. { ret bcx; }
+ ty::closure_shared. { ret incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr)); }
+ ty::closure_send. { /* hard case: */ }
+ }
+
+ // Hard case, a deep copy:
+ let ccx = bcx_ccx(bcx);
+ let llopaquecboxty = T_opaque_cbox_ptr(ccx);
+ let cbox_in = Load(bcx, cboxptr);
+ make_null_test(bcx, cbox_in) {|bcx|
+ // Load the size from the type descr found in the cbox
+ let cbox_in = PointerCast(bcx, cbox_in, llopaquecboxty);
+ let tydescptr = GEPi(bcx, cbox_in, [0, abi::cbox_elt_tydesc]);
+ let tydesc = Load(bcx, tydescptr);
+ let tydesc = PointerCast(bcx, tydesc, T_ptr(ccx.tydesc_type));
+ let sz = Load(bcx, GEPi(bcx, tydesc, [0, abi::tydesc_field_size]));
+
+ // Allocate memory, update original ptr, and copy existing data
+ let malloc = ccx.upcalls.shared_malloc;
+ let cbox_out = Call(bcx, malloc, [sz, tydesc]);
+ let cbox_out = PointerCast(bcx, cbox_out, llopaquecboxty);
+ let {bcx, val: _} = call_memmove(bcx, cbox_out, cbox_in, sz);
+ Store(bcx, cbox_out, cboxptr);
+
+ // Take the data in the tuple
+ let ti = none;
+ call_tydesc_glue_full(bcx, cbox_out, tydesc,
+ abi::tydesc_field_take_glue, ti);
+ bcx
+ }
+}
+
+fn make_opaque_cbox_drop_glue(
+ bcx: @block_ctxt,
+ ck: ty::closure_kind,
+ cboxptr: ValueRef) // ptr to the opaque closure
+ -> @block_ctxt {
+ alt ck {
+ ty::closure_block. { bcx }
+ ty::closure_shared. {
+ decr_refcnt_maybe_free(bcx, Load(bcx, cboxptr),
+ ty::mk_opaque_closure_ptr(bcx_tcx(bcx), ck))
+ }
+ ty::closure_send. {
+ free_ty(bcx, Load(bcx, cboxptr),
+ ty::mk_opaque_closure_ptr(bcx_tcx(bcx), ck))
+ }
+ }
+}
+
+fn make_opaque_cbox_free_glue(
+ bcx: @block_ctxt,
+ ck: ty::closure_kind,
+ cbox: ValueRef) // ptr to the opaque closure
+ -> @block_ctxt {
+ alt ck {
+ ty::closure_block. { ret bcx; }
+ ty::closure_shared. | ty::closure_send. { /* hard cases: */ }
+ }
+