]> git.proxmox.com Git - rustc.git/blame - src/librustc_trans/tvec.rs
New upstream version 1.12.0+dfsg1
[rustc.git] / src / librustc_trans / tvec.rs
CommitLineData
1a4d82fc
JJ
1// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11#![allow(non_camel_case_types)]
12
1a4d82fc 13use llvm;
c34b1796 14use llvm::ValueRef;
54a0048b
SL
15use base::*;
16use base;
17use build::*;
18use cleanup;
19use cleanup::CleanupMethods;
20use common::*;
21use consts;
22use datum::*;
23use debuginfo::DebugLoc;
24use expr::{Dest, Ignore, SaveIn};
25use expr;
26use machine::llsize_of_alloc;
27use type_::Type;
28use type_of;
29use value::Value;
30use rustc::ty::{self, Ty};
31
32use rustc::hir;
5bcae85e 33use rustc_const_eval::eval_length;
e9174d1e 34
b039eaaf 35use syntax::ast;
1a4d82fc
JJ
36use syntax::parse::token::InternedString;
37
54a0048b 38#[derive(Copy, Clone, Debug)]
c34b1796
AL
39struct VecTypes<'tcx> {
40 unit_ty: Ty<'tcx>,
41 llunit_ty: Type
1a4d82fc
JJ
42}
43
1a4d82fc 44pub fn trans_fixed_vstore<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
e9174d1e 45 expr: &hir::Expr,
1a4d82fc
JJ
46 dest: expr::Dest)
47 -> Block<'blk, 'tcx> {
48 //!
49 //
50 // [...] allocates a fixed-size array and moves it around "by value".
51 // In this case, it means that the caller has already given us a location
52 // to store the array of the suitable size, so all we have to do is
53 // generate the content.
54
54a0048b 55 debug!("trans_fixed_vstore(expr={:?}, dest={:?})", expr, dest);
1a4d82fc
JJ
56
57 let vt = vec_types_from_expr(bcx, expr);
58
59 return match dest {
60 Ignore => write_content(bcx, &vt, expr, expr, dest),
61 SaveIn(lldest) => {
62 // lldest will have type *[T x N], but we want the type *T,
63 // so use GEP to convert:
e9174d1e 64 let lldest = StructGEP(bcx, lldest, 0);
1a4d82fc
JJ
65 write_content(bcx, &vt, expr, expr, SaveIn(lldest))
66 }
67 };
68}
69
70/// &[...] allocates memory on the stack and writes the values into it, returning the vector (the
71/// caller must make the reference). "..." is similar except that the memory can be statically
72/// allocated and we return a reference (strings are always by-ref).
73pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
e9174d1e
SL
74 slice_expr: &hir::Expr,
75 content_expr: &hir::Expr)
1a4d82fc
JJ
76 -> DatumBlock<'blk, 'tcx, Expr> {
77 let fcx = bcx.fcx;
1a4d82fc
JJ
78 let mut bcx = bcx;
79
62682a34
SL
80 debug!("trans_slice_vec(slice_expr={:?})",
81 slice_expr);
1a4d82fc
JJ
82
83 let vec_ty = node_id_type(bcx, slice_expr.id);
84
85 // Handle the "..." case (returns a slice since strings are always unsized):
e9174d1e 86 if let hir::ExprLit(ref lit) = content_expr.node {
7453a54e 87 if let ast::LitKind::Str(ref s, _) = lit.node {
1a4d82fc
JJ
88 let scratch = rvalue_scratch_datum(bcx, vec_ty, "");
89 bcx = trans_lit_str(bcx,
90 content_expr,
91 s.clone(),
92 SaveIn(scratch.val));
93 return DatumBlock::new(bcx, scratch.to_expr_datum());
94 }
95 }
96
97 // Handle the &[...] case:
98 let vt = vec_types_from_expr(bcx, content_expr);
99 let count = elements_required(bcx, content_expr);
54a0048b 100 debug!(" vt={:?}, count={}", vt, count);
1a4d82fc 101
c1a9b12d 102 let fixed_ty = bcx.tcx().mk_array(vt.unit_ty, count);
1a4d82fc 103
85aaf69f
SL
104 // Always create an alloca even if zero-sized, to preserve
105 // the non-null invariant of the inner slice ptr
9cc50fc6
SL
106 let llfixed;
107 // Issue 30018: ensure state is initialized as dropped if necessary.
108 if fcx.type_needs_drop(vt.unit_ty) {
109 llfixed = base::alloc_ty_init(bcx, fixed_ty, InitAlloca::Dropped, "");
110 } else {
111 let uninit = InitAlloca::Uninit("fcx says vt.unit_ty is non-drop");
112 llfixed = base::alloc_ty_init(bcx, fixed_ty, uninit, "");
113 call_lifetime_start(bcx, llfixed);
114 };
1a4d82fc 115
85aaf69f 116 if count > 0 {
1a4d82fc 117 // Arrange for the backing array to be cleaned up.
1a4d82fc 118 let cleanup_scope = cleanup::temporary_scope(bcx.tcx(), content_expr.id);
85aaf69f 119 fcx.schedule_lifetime_end(cleanup_scope, llfixed);
c1a9b12d 120 fcx.schedule_drop_mem(cleanup_scope, llfixed, fixed_ty, None);
1a4d82fc
JJ
121
122 // Generate the content into the backing array.
85aaf69f
SL
123 // llfixed has type *[T x N], but we want the type *T,
124 // so use GEP to convert
125 bcx = write_content(bcx, &vt, slice_expr, content_expr,
e9174d1e 126 SaveIn(StructGEP(bcx, llfixed, 0)));
1a4d82fc
JJ
127 };
128
129 immediate_rvalue_bcx(bcx, llfixed, vec_ty).to_expr_datumblock()
130}
131
132/// Literal strings translate to slices into static memory. This is different from
133/// trans_slice_vstore() above because it doesn't need to copy the content anywhere.
134pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
e9174d1e 135 lit_expr: &hir::Expr,
1a4d82fc
JJ
136 str_lit: InternedString,
137 dest: Dest)
138 -> Block<'blk, 'tcx> {
54a0048b 139 debug!("trans_lit_str(lit_expr={:?}, dest={:?})", lit_expr, dest);
1a4d82fc
JJ
140
141 match dest {
142 Ignore => bcx,
143 SaveIn(lldest) => {
85aaf69f 144 let bytes = str_lit.len();
1a4d82fc
JJ
145 let llbytes = C_uint(bcx.ccx(), bytes);
146 let llcstr = C_cstr(bcx.ccx(), str_lit, false);
147 let llcstr = consts::ptrcast(llcstr, Type::i8p(bcx.ccx()));
e9174d1e
SL
148 Store(bcx, llcstr, expr::get_dataptr(bcx, lldest));
149 Store(bcx, llbytes, expr::get_meta(bcx, lldest));
1a4d82fc
JJ
150 bcx
151 }
152 }
153}
154
c34b1796
AL
155fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
156 vt: &VecTypes<'tcx>,
e9174d1e
SL
157 vstore_expr: &hir::Expr,
158 content_expr: &hir::Expr,
c34b1796
AL
159 dest: Dest)
160 -> Block<'blk, 'tcx> {
1a4d82fc
JJ
161 let _icx = push_ctxt("tvec::write_content");
162 let fcx = bcx.fcx;
163 let mut bcx = bcx;
164
54a0048b
SL
165 debug!("write_content(vt={:?}, dest={:?}, vstore_expr={:?})",
166 vt, dest, vstore_expr);
1a4d82fc
JJ
167
168 match content_expr.node {
e9174d1e 169 hir::ExprLit(ref lit) => {
1a4d82fc 170 match lit.node {
7453a54e 171 ast::LitKind::Str(ref s, _) => {
1a4d82fc
JJ
172 match dest {
173 Ignore => return bcx,
174 SaveIn(lldest) => {
85aaf69f 175 let bytes = s.len();
1a4d82fc
JJ
176 let llbytes = C_uint(bcx.ccx(), bytes);
177 let llcstr = C_cstr(bcx.ccx(), (*s).clone(), false);
54a0048b
SL
178 if !bcx.unreachable.get() {
179 base::call_memcpy(&B(bcx), lldest, llcstr, llbytes, 1);
180 }
1a4d82fc
JJ
181 return bcx;
182 }
183 }
184 }
185 _ => {
54a0048b 186 span_bug!(content_expr.span, "unexpected evec content");
1a4d82fc
JJ
187 }
188 }
189 }
e9174d1e 190 hir::ExprVec(ref elements) => {
1a4d82fc
JJ
191 match dest {
192 Ignore => {
85aaf69f 193 for element in elements {
7453a54e 194 bcx = expr::trans_into(bcx, &element, Ignore);
1a4d82fc
JJ
195 }
196 }
197
198 SaveIn(lldest) => {
199 let temp_scope = fcx.push_custom_cleanup_scope();
200 for (i, element) in elements.iter().enumerate() {
201 let lleltptr = GEPi(bcx, lldest, &[i]);
54a0048b
SL
202 debug!("writing index {} with lleltptr={:?}",
203 i, Value(lleltptr));
7453a54e 204 bcx = expr::trans_into(bcx, &element,
1a4d82fc
JJ
205 SaveIn(lleltptr));
206 let scope = cleanup::CustomScope(temp_scope);
9cc50fc6
SL
207 // Issue #30822: mark memory as dropped after running destructor
208 fcx.schedule_drop_and_fill_mem(scope, lleltptr, vt.unit_ty, None);
1a4d82fc
JJ
209 }
210 fcx.pop_custom_cleanup_scope(temp_scope);
211 }
212 }
213 return bcx;
214 }
e9174d1e 215 hir::ExprRepeat(ref element, ref count_expr) => {
1a4d82fc
JJ
216 match dest {
217 Ignore => {
7453a54e 218 return expr::trans_into(bcx, &element, Ignore);
1a4d82fc
JJ
219 }
220 SaveIn(lldest) => {
5bcae85e 221 match eval_length(bcx.tcx(), &count_expr, "repeat count").unwrap() {
7453a54e
SL
222 0 => expr::trans_into(bcx, &element, Ignore),
223 1 => expr::trans_into(bcx, &element, SaveIn(lldest)),
1a4d82fc 224 count => {
7453a54e 225 let elem = unpack_datum!(bcx, expr::trans(bcx, &element));
1a4d82fc
JJ
226 let bcx = iter_vec_loop(bcx, lldest, vt,
227 C_uint(bcx.ccx(), count),
228 |set_bcx, lleltptr, _| {
229 elem.shallow_copy(set_bcx, lleltptr)
230 });
1a4d82fc
JJ
231 bcx
232 }
233 }
234 }
235 }
236 }
237 _ => {
54a0048b 238 span_bug!(content_expr.span, "unexpected vec content");
1a4d82fc
JJ
239 }
240 }
241}
242
e9174d1e 243fn vec_types_from_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, vec_expr: &hir::Expr)
c34b1796 244 -> VecTypes<'tcx> {
1a4d82fc 245 let vec_ty = node_id_type(bcx, vec_expr.id);
c1a9b12d 246 vec_types(bcx, vec_ty.sequence_element_type(bcx.tcx()))
1a4d82fc
JJ
247}
248
c34b1796
AL
249fn vec_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, unit_ty: Ty<'tcx>)
250 -> VecTypes<'tcx> {
1a4d82fc
JJ
251 VecTypes {
252 unit_ty: unit_ty,
c34b1796 253 llunit_ty: type_of::type_of(bcx.ccx(), unit_ty)
1a4d82fc
JJ
254 }
255}
256
e9174d1e 257fn elements_required(bcx: Block, content_expr: &hir::Expr) -> usize {
1a4d82fc
JJ
258 //! Figure out the number of elements we need to store this content
259
260 match content_expr.node {
e9174d1e 261 hir::ExprLit(ref lit) => {
1a4d82fc 262 match lit.node {
7453a54e 263 ast::LitKind::Str(ref s, _) => s.len(),
1a4d82fc 264 _ => {
54a0048b 265 span_bug!(content_expr.span, "unexpected evec content")
1a4d82fc
JJ
266 }
267 }
268 },
e9174d1e
SL
269 hir::ExprVec(ref es) => es.len(),
270 hir::ExprRepeat(_, ref count_expr) => {
5bcae85e 271 eval_length(bcx.tcx(), &count_expr, "repeat count").unwrap()
1a4d82fc 272 }
54a0048b 273 _ => span_bug!(content_expr.span, "unexpected vec content")
1a4d82fc
JJ
274 }
275}
276
277/// Converts a fixed-length vector into the slice pair. The vector should be stored in `llval`
278/// which should be by ref.
279pub fn get_fixed_base_and_len(bcx: Block,
280 llval: ValueRef,
c34b1796 281 vec_length: usize)
1a4d82fc
JJ
282 -> (ValueRef, ValueRef) {
283 let ccx = bcx.ccx();
284
285 let base = expr::get_dataptr(bcx, llval);
286 let len = C_uint(ccx, vec_length);
287 (base, len)
288}
289
1a4d82fc
JJ
290/// Converts a vector into the slice pair. The vector should be stored in `llval` which should be
291/// by-reference. If you have a datum, you would probably prefer to call
292/// `Datum::get_base_and_len()` which will handle any conversions for you.
c34b1796
AL
293pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
294 llval: ValueRef,
295 vec_ty: Ty<'tcx>)
296 -> (ValueRef, ValueRef) {
1a4d82fc 297 match vec_ty.sty {
62682a34
SL
298 ty::TyArray(_, n) => get_fixed_base_and_len(bcx, llval, n),
299 ty::TySlice(_) | ty::TyStr => {
c34b1796 300 let base = Load(bcx, expr::get_dataptr(bcx, llval));
e9174d1e 301 let len = Load(bcx, expr::get_meta(bcx, llval));
c34b1796
AL
302 (base, len)
303 }
1a4d82fc
JJ
304
305 // Only used for pattern matching.
c1a9b12d 306 ty::TyBox(ty) | ty::TyRef(_, ty::TypeAndMut{ty, ..}) => {
c34b1796
AL
307 let inner = if type_is_sized(bcx.tcx(), ty) {
308 Load(bcx, llval)
309 } else {
310 llval
311 };
312 get_base_and_len(bcx, inner, ty)
1a4d82fc 313 },
54a0048b 314 _ => bug!("unexpected type in get_base_and_len"),
1a4d82fc
JJ
315 }
316}
317
c34b1796
AL
318fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
319 data_ptr: ValueRef,
320 vt: &VecTypes<'tcx>,
321 count: ValueRef,
322 f: F)
323 -> Block<'blk, 'tcx> where
1a4d82fc
JJ
324 F: FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
325{
326 let _icx = push_ctxt("tvec::iter_vec_loop");
1a4d82fc 327
c34b1796
AL
328 if bcx.unreachable.get() {
329 return bcx;
330 }
331
332 let fcx = bcx.fcx;
1a4d82fc 333 let loop_bcx = fcx.new_temp_block("expr_repeat");
85aaf69f 334 let next_bcx = fcx.new_temp_block("expr_repeat: next");
1a4d82fc 335
85aaf69f 336 Br(bcx, loop_bcx.llbb, DebugLoc::None);
1a4d82fc 337
85aaf69f
SL
338 let loop_counter = Phi(loop_bcx, bcx.ccx().int_type(),
339 &[C_uint(bcx.ccx(), 0 as usize)], &[bcx.llbb]);
1a4d82fc 340
85aaf69f 341 let bcx = loop_bcx;
1a4d82fc 342
c34b1796 343 let lleltptr = if llsize_of_alloc(bcx.ccx(), vt.llunit_ty) == 0 {
85aaf69f
SL
344 data_ptr
345 } else {
346 InBoundsGEP(bcx, data_ptr, &[loop_counter])
347 };
348 let bcx = f(bcx, lleltptr, vt.unit_ty);
9346a6ac 349 let plusone = Add(bcx, loop_counter, C_uint(bcx.ccx(), 1usize), DebugLoc::None);
85aaf69f 350 AddIncomingToPhi(loop_counter, plusone, bcx.llbb);
1a4d82fc 351
5bcae85e 352 let cond_val = ICmp(bcx, llvm::IntNE, plusone, count, DebugLoc::None);
85aaf69f 353 CondBr(bcx, cond_val, loop_bcx.llbb, next_bcx.llbb, DebugLoc::None);
1a4d82fc
JJ
354
355 next_bcx
356}
357
358pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
359 data_ptr: ValueRef,
360 unit_ty: Ty<'tcx>,
361 len: ValueRef,
362 f: F)
363 -> Block<'blk, 'tcx> where
364 F: FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
365{
366 let _icx = push_ctxt("tvec::iter_vec_raw");
367 let fcx = bcx.fcx;
368
369 let vt = vec_types(bcx, unit_ty);
1a4d82fc 370
c34b1796 371 if llsize_of_alloc(bcx.ccx(), vt.llunit_ty) == 0 {
1a4d82fc 372 // Special-case vectors with elements of size 0 so they don't go out of bounds (#9890)
85aaf69f 373 iter_vec_loop(bcx, data_ptr, &vt, len, f)
1a4d82fc
JJ
374 } else {
375 // Calculate the last pointer address we want to handle.
85aaf69f 376 let data_end_ptr = InBoundsGEP(bcx, data_ptr, &[len]);
1a4d82fc
JJ
377
378 // Now perform the iteration.
379 let header_bcx = fcx.new_temp_block("iter_vec_loop_header");
85aaf69f 380 Br(bcx, header_bcx.llbb, DebugLoc::None);
1a4d82fc
JJ
381 let data_ptr =
382 Phi(header_bcx, val_ty(data_ptr), &[data_ptr], &[bcx.llbb]);
383 let not_yet_at_end =
5bcae85e 384 ICmp(header_bcx, llvm::IntNE, data_ptr, data_end_ptr, DebugLoc::None);
1a4d82fc
JJ
385 let body_bcx = fcx.new_temp_block("iter_vec_loop_body");
386 let next_bcx = fcx.new_temp_block("iter_vec_next");
85aaf69f 387 CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb, DebugLoc::None);
c34b1796 388 let body_bcx = f(body_bcx, data_ptr, unit_ty);
1a4d82fc 389 AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr,
85aaf69f 390 &[C_int(bcx.ccx(), 1)]),
1a4d82fc 391 body_bcx.llbb);
85aaf69f 392 Br(body_bcx, header_bcx.llbb, DebugLoc::None);
1a4d82fc
JJ
393 next_bcx
394 }
395}