]> git.lizzy.rs Git - rust.git/blob - src/comp/middle/trans_uniq.rs
5c4905207c85495711bd248aa93297afa7cb25b8
[rust.git] / src / comp / middle / trans_uniq.rs
1 import syntax::ast;
2 import lib::llvm::llvm::ValueRef;
3 import trans_common::*;
4 import trans_build::*;
5 import trans::{
6     trans_shared_malloc,
7     type_of_inner,
8     size_of,
9     node_id_type,
10     INIT,
11     trans_shared_free,
12     drop_ty,
13     new_sub_block_ctxt,
14     load_if_immediate,
15     dest
16 };
17
18 export trans_uniq, make_free_glue, type_is_unique_box, autoderef, duplicate,
19        alloc_uniq;
20
21 pure fn type_is_unique_box(bcx: @block_ctxt, ty: ty::t) -> bool {
22     ty::type_is_unique_box(bcx_tcx(bcx), ty)
23 }
24
25 fn trans_uniq(bcx: @block_ctxt, contents: @ast::expr,
26               node_id: ast::node_id, dest: dest) -> @block_ctxt {
27     let uniq_ty = node_id_type(bcx_ccx(bcx), node_id);
28     check type_is_unique_box(bcx, uniq_ty);
29     let {bcx, val: llptr} = alloc_uniq(bcx, uniq_ty);
30     add_clean_free(bcx, llptr, true);
31     bcx = trans::trans_expr_save_in(bcx, contents, llptr);
32     revoke_clean(bcx, llptr);
33     ret trans::store_in_dest(bcx, llptr, dest);
34 }
35
36 fn alloc_uniq(bcx: @block_ctxt, uniq_ty: ty::t)
37     : type_is_unique_box(bcx, uniq_ty) -> result {
38     let contents_ty = content_ty(bcx, uniq_ty);
39     let {bcx, val: llsz} = size_of(bcx, contents_ty);
40     let ccx = bcx_ccx(bcx);
41     check non_ty_var(ccx, contents_ty);
42     let llptrty = T_ptr(type_of_inner(ccx, bcx.sp, contents_ty));
43     ret trans_shared_malloc(bcx, llptrty, llsz);
44 }
45
46 fn make_free_glue(cx: @block_ctxt, vptr: ValueRef, t: ty::t)
47     : type_is_unique_box(cx, t) -> @block_ctxt {
48
49     let bcx = cx;
50     let free_cx = new_sub_block_ctxt(bcx, "uniq_free");
51     let next_cx = new_sub_block_ctxt(bcx, "uniq_free_next");
52     let null_test = IsNull(bcx, vptr);
53     CondBr(bcx, null_test, next_cx.llbb, free_cx.llbb);
54
55     let bcx = free_cx;
56     let bcx = drop_ty(bcx, vptr, content_ty(cx, t));
57     let bcx = trans_shared_free(bcx, vptr);
58     Br(bcx, next_cx.llbb);
59     next_cx
60 }
61
62 fn content_ty(bcx: @block_ctxt, t: ty::t)
63     : type_is_unique_box(bcx, t) -> ty::t {
64
65     alt ty::struct(bcx_tcx(bcx), t) {
66       ty::ty_uniq({ty: ct, _}) { ct }
67     }
68 }
69
70 fn autoderef(bcx: @block_ctxt, v: ValueRef, t: ty::t)
71     : type_is_unique_box(bcx, t) -> {v: ValueRef, t: ty::t} {
72
73     let content_ty = content_ty(bcx, t);
74     ret {v: v, t: content_ty};
75 }
76
77 fn duplicate(bcx: @block_ctxt, v: ValueRef, t: ty::t)
78     : type_is_unique_box(bcx, t) -> result {
79
80     let content_ty = content_ty(bcx, t);
81     let {bcx, val: llptr} = alloc_uniq(bcx, t);
82
83     let src = load_if_immediate(bcx, v, content_ty);
84     let dst = llptr;
85     let bcx = trans::copy_val(bcx, INIT, dst, src, content_ty);
86     ret rslt(bcx, dst);
87 }