]> git.lizzy.rs Git - rust.git/blob - src/comp/middle/trans_uniq.rs
faa7c812054b3571bef7242cadbc535c862b33ee
[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     move_val_if_temp,
10     node_id_type,
11     trans_lval,
12     INIT,
13     trans_shared_free,
14     drop_ty,
15     new_sub_block_ctxt,
16     load_if_immediate
17 };
18
19 export trans_uniq, make_free_glue, type_is_unique_box, copy_val,
20 autoderef, duplicate;
21
22 pure fn type_is_unique_box(bcx: @block_ctxt, ty: ty::t) -> bool {
23     unchecked {
24         ty::type_is_unique_box(bcx_tcx(bcx), ty)
25     }
26 }
27
28 fn trans_uniq(cx: @block_ctxt, contents: @ast::expr,
29               node_id: ast::node_id) -> result {
30     let bcx = cx;
31
32     let lv = trans_lval(bcx, contents);
33     bcx = lv.bcx;
34
35     let uniq_ty = node_id_type(bcx_ccx(cx), node_id);
36     check type_is_unique_box(bcx, uniq_ty);
37     let content_ty = content_ty(bcx, uniq_ty);
38     let {bcx, val: llptr} = alloc_uniq(bcx, uniq_ty);
39
40     add_clean_temp(bcx, llptr, uniq_ty);
41
42     bcx = move_val_if_temp(bcx, INIT, llptr, lv,
43                            content_ty);
44
45     ret rslt(bcx, llptr);
46 }
47
48 fn alloc_uniq(cx: @block_ctxt, uniq_ty: ty::t)
49     : type_is_unique_box(cx, uniq_ty) -> result {
50
51     let bcx = cx;
52     let contents_ty = content_ty(bcx, uniq_ty);
53     let r = size_of(bcx, contents_ty);
54     bcx = r.bcx;
55     let llsz = r.val;
56
57     let ccx = bcx_ccx(bcx);
58     check non_ty_var(ccx, contents_ty);
59     let llptrty = T_ptr(type_of_inner(ccx, bcx.sp, contents_ty));
60
61     r = trans_shared_malloc(bcx, llptrty, llsz);
62     bcx = r.bcx;
63     let llptr = r.val;
64
65     ret rslt(bcx, llptr);
66 }
67
68 fn make_free_glue(cx: @block_ctxt, v: ValueRef, t: ty::t)
69     : type_is_unique_box(cx, t) -> @block_ctxt {
70
71     let bcx = cx;
72     let free_cx = new_sub_block_ctxt(bcx, "uniq_free");
73     let next_cx = new_sub_block_ctxt(bcx, "uniq_free_next");
74     let vptr = Load(bcx, v);
75     let null_test = IsNull(bcx, vptr);
76     CondBr(bcx, null_test, next_cx.llbb, free_cx.llbb);
77
78     let bcx = free_cx;
79     let bcx = drop_ty(bcx, vptr, content_ty(cx, t));
80     let bcx = trans_shared_free(bcx, vptr);
81     Store(bcx, C_null(val_ty(vptr)), v);
82     Br(bcx, next_cx.llbb);
83
84     next_cx
85 }
86
87 fn content_ty(bcx: @block_ctxt, t: ty::t)
88     : type_is_unique_box(bcx, t) -> ty::t {
89
90     alt ty::struct(bcx_tcx(bcx), t) {
91       ty::ty_uniq({ty: ct, _}) { ct }
92     }
93 }
94
95 fn copy_val(cx: @block_ctxt, dst: ValueRef, src: ValueRef,
96             ty: ty::t) : type_is_unique_box(cx, ty) -> @block_ctxt {
97
98     let content_ty = content_ty(cx, ty);
99     let {bcx, val: llptr} = alloc_uniq(cx, ty);
100     Store(bcx, llptr, dst);
101
102     let src = Load(bcx, src);
103     let dst = llptr;
104     let bcx = trans::copy_val(bcx, INIT, dst, src, content_ty);
105     ret bcx;
106 }
107
108 fn autoderef(bcx: @block_ctxt, v: ValueRef, t: ty::t)
109     : type_is_unique_box(bcx, t) -> {v: ValueRef, t: ty::t} {
110
111     let content_ty = content_ty(bcx, t);
112     ret {v: v, t: content_ty};
113 }
114
115 fn duplicate(bcx: @block_ctxt, v: ValueRef, t: ty::t)
116     : type_is_unique_box(bcx, t) -> @block_ctxt {
117
118     let content_ty = content_ty(bcx, t);
119     let {bcx, val: llptr} = alloc_uniq(bcx, t);
120
121     let src = Load(bcx, v);
122     let src = load_if_immediate(bcx, src, content_ty);
123     let dst = llptr;
124     let bcx = trans::copy_val(bcx, INIT, dst, src, content_ty);
125     Store(bcx, dst, v);
126     ret bcx;
127 }