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
13 use back::abi;
14 use lib;
15 use lib::llvm::{llvm, ValueRef};
16 use middle::lang_items::StrDupUniqFnLangItem;
17 use middle::trans::base::*;
18 use middle::trans::base;
19 use middle::trans::build::*;
20 use middle::trans::callee;
21 use middle::trans::cleanup;
22 use middle::trans::cleanup::CleanupMethods;
23 use middle::trans::common::*;
24 use middle::trans::datum::*;
25 use middle::trans::expr::{Dest, Ignore, SaveIn};
26 use middle::trans::expr;
27 use middle::trans::glue;
28 use middle::trans::machine::{llsize_of, nonzero_llsize_of, llsize_of_alloc};
29 use middle::trans::type_::Type;
30 use middle::trans::type_of;
31 use middle::ty;
32 use util::ppaux::ty_to_str;
33
34 use syntax::ast;
35 use syntax::parse::token::InternedString;
36
37 pub fn get_fill(bcx: &Block, vptr: ValueRef) -> ValueRef {
38 let _icx = push_ctxt("tvec::get_fill");
39 Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_fill]))
40 }
41
42 pub fn get_dataptr(bcx: &Block, vptr: ValueRef) -> ValueRef {
43 let _icx = push_ctxt("tvec::get_dataptr");
44 GEPi(bcx, vptr, [0u, abi::vec_elt_elems, 0u])
45 }
46
47 pub fn pointer_add_byte(bcx: &Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
48 let _icx = push_ctxt("tvec::pointer_add_byte");
49 let old_ty = val_ty(ptr);
50 let bptr = PointerCast(bcx, ptr, Type::i8p(bcx.ccx()));
51 return PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty);
52 }
53
54 pub fn make_drop_glue_unboxed<'a>(
55 bcx: &'a Block<'a>,
56 vptr: ValueRef,
57 unit_ty: ty::t)
58 -> &'a Block<'a> {
59 let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
60 let tcx = bcx.tcx();
61 if ty::type_needs_drop(tcx, unit_ty) {
62 let fill = get_fill(bcx, vptr);
63 let dataptr = get_dataptr(bcx, vptr);
64 iter_vec_raw(bcx, dataptr, unit_ty, fill, glue::drop_ty)
65 } else { bcx }
66 }
67
68 pub struct VecTypes {
69 pub unit_ty: ty::t,
70 pub llunit_ty: Type,
71 pub llunit_size: ValueRef,
72 pub llunit_alloc_size: u64
73 }
74
75 impl VecTypes {
76 pub fn to_str(&self, ccx: &CrateContext) -> ~str {
77 format!("VecTypes \\{unit_ty={}, llunit_ty={}, llunit_size={}, \
78 llunit_alloc_size={}\\}",
79 ty_to_str(ccx.tcx(), self.unit_ty),
80 ccx.tn.type_to_str(self.llunit_ty),
81 ccx.tn.val_to_str(self.llunit_size),
82 self.llunit_alloc_size)
83 }
84 }
85
86 pub fn trans_fixed_vstore<'a>(
87 bcx: &'a Block<'a>,
88 vstore_expr: &ast::Expr,
89 content_expr: &ast::Expr,
90 dest: expr::Dest)
91 -> &'a Block<'a> {
92 //!
93 //
94 // [...] allocates a fixed-size array and moves it around "by value".
95 // In this case, it means that the caller has already given us a location
96 // to store the array of the suitable size, so all we have to do is
97 // generate the content.
98
99 debug!("trans_fixed_vstore(vstore_expr={}, dest={:?})",
100 bcx.expr_to_str(vstore_expr), dest.to_str(bcx.ccx()));
101
102 let vt = vec_types_from_expr(bcx, vstore_expr);
103
104 return match dest {
105 Ignore => write_content(bcx, &vt, vstore_expr, content_expr, dest),
106 SaveIn(lldest) => {
107 // lldest will have type *[T x N], but we want the type *T,
108 // so use GEP to convert:
109 let lldest = GEPi(bcx, lldest, [0, 0]);
110 write_content(bcx, &vt, vstore_expr, content_expr, SaveIn(lldest))
111 }
112 };
113 }
114
115 pub fn trans_slice_vstore<'a>(
116 bcx: &'a Block<'a>,
117 vstore_expr: &ast::Expr,
118 content_expr: &ast::Expr,
119 dest: expr::Dest)
120 -> &'a Block<'a> {
121 /*!
122 * &[...] allocates memory on the stack and writes the values into it,
123 * returning a slice (pair of ptr, len). &"..." is similar except that
124 * the memory can be statically allocated.
125 */
126
127 let fcx = bcx.fcx;
128 let ccx = fcx.ccx;
129 let mut bcx = bcx;
130
131 debug!("trans_slice_vstore(vstore_expr={}, dest={})",
132 bcx.expr_to_str(vstore_expr), dest.to_str(ccx));
133
134 // Handle the &"..." case:
135 match content_expr.node {
136 ast::ExprLit(lit) => {
137 match lit.node {
138 ast::LitStr(ref s, _) => {
139 return trans_lit_str(bcx,
140 content_expr,
141 s.clone(),
142 dest)
143 }
144 _ => {}
145 }
146 }
147 _ => {}
148 }
149
150 // Handle the &[...] case:
151 let vt = vec_types_from_expr(bcx, vstore_expr);
152 let count = elements_required(bcx, content_expr);
153 debug!("vt={}, count={:?}", vt.to_str(ccx), count);
154
155 let llcount = C_uint(ccx, count);
156 let llfixed;
157 if count == 0 {
158 // Zero-length array: just use NULL as the data pointer
159 llfixed = C_null(vt.llunit_ty.ptr_to());
160 } else {
161 // Make a fixed-length backing array and allocate it on the stack.
162 llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
163
164 // Arrange for the backing array to be cleaned up.
165 let fixed_ty = ty::mk_vec(bcx.tcx(),
166 ty::mt {ty: vt.unit_ty,
167 mutbl: ast::MutMutable},
168 Some(count));
169 let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty).ptr_to();
170 let llfixed_casted = BitCast(bcx, llfixed, llfixed_ty);
171 let cleanup_scope = cleanup::temporary_scope(bcx.tcx(), content_expr.id);
172 fcx.schedule_drop_mem(cleanup_scope, llfixed_casted, fixed_ty);
173
174 // Generate the content into the backing array.
175 bcx = write_content(bcx, &vt, vstore_expr,
176 content_expr, SaveIn(llfixed));
177 }
178
179 // Finally, create the slice pair itself.
180 match dest {
181 Ignore => {}
182 SaveIn(lldest) => {
183 Store(bcx, llfixed, GEPi(bcx, lldest, [0u, abi::slice_elt_base]));
184 Store(bcx, llcount, GEPi(bcx, lldest, [0u, abi::slice_elt_len]));
185 }
186 }
187
188 return bcx;
189 }
190
191 pub fn trans_lit_str<'a>(
192 bcx: &'a Block<'a>,
193 lit_expr: &ast::Expr,
194 str_lit: InternedString,
195 dest: Dest)
196 -> &'a Block<'a> {
197 /*!
198 * Literal strings translate to slices into static memory. This is
199 * different from trans_slice_vstore() above because it does need to copy
200 * the content anywhere.
201 */
202
203 debug!("trans_lit_str(lit_expr={}, dest={})",
204 bcx.expr_to_str(lit_expr),
205 dest.to_str(bcx.ccx()));
206
207 match dest {
208 Ignore => bcx,
209 SaveIn(lldest) => {
210 unsafe {
211 let bytes = str_lit.get().len();
212 let llbytes = C_uint(bcx.ccx(), bytes);
213 let llcstr = C_cstr(bcx.ccx(), str_lit, false);
214 let llcstr = llvm::LLVMConstPointerCast(llcstr, Type::i8p(bcx.ccx()).to_ref());
215 Store(bcx, llcstr,
216 GEPi(bcx, lldest, [0u, abi::slice_elt_base]));
217 Store(bcx, llbytes,
218 GEPi(bcx, lldest, [0u, abi::slice_elt_len]));
219 bcx
220 }
221 }
222 }
223 }
224
225
226 pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,
227 vstore_expr: &ast::Expr,
228 content_expr: &ast::Expr)
229 -> DatumBlock<'a, Expr> {
230 /*!
231 * ~[...] and "...".to_owned() allocate boxes in the exchange heap and write
232 * the array elements into them.
233 */
234
235 debug!("trans_uniq_vstore(vstore_expr={})", bcx.expr_to_str(vstore_expr));
236 let fcx = bcx.fcx;
237 let ccx = fcx.ccx;
238
239 // Handle "".to_owned().
240 match content_expr.node {
241 ast::ExprLit(lit) => {
242 match lit.node {
243 ast::LitStr(ref s, _) => {
244 let llptrval = C_cstr(ccx, (*s).clone(), false);
245 let llptrval = PointerCast(bcx, llptrval, Type::i8p(ccx));
246 let llsizeval = C_uint(ccx, s.get().len());
247 let typ = ty::mk_uniq(bcx.tcx(), ty::mk_str(bcx.tcx()));
248 let lldestval = rvalue_scratch_datum(bcx,
249 typ,
250 "");
251 let alloc_fn = langcall(bcx,
252 Some(lit.span),
253 "",
254 StrDupUniqFnLangItem);
255 let bcx = callee::trans_lang_call(
256 bcx,
257 alloc_fn,
258 [ llptrval, llsizeval ],
259 Some(expr::SaveIn(lldestval.val))).bcx;
260 return DatumBlock(bcx, lldestval).to_expr_datumblock();
261 }
262 _ => {}
263 }
264 }
265 _ => {}
266 }
267
268 let vec_ty = node_id_type(bcx, vstore_expr.id);
269 let vt = vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
270 let count = elements_required(bcx, content_expr);
271
272 let llunitty = type_of::type_of(ccx, vt.unit_ty);
273 let unit_sz = nonzero_llsize_of(ccx, llunitty);
274
275 let fill = Mul(bcx, C_uint(ccx, count), unit_sz);
276 let alloc = if count < 4u { Mul(bcx, C_int(ccx, 4), unit_sz) }
277 else { fill };
278
279 let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type));
280
281 let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, vec_ty, vecsize);
282 Store(bcx, fill, GEPi(bcx, val, [0u, abi::vec_elt_fill]));
283 Store(bcx, alloc, GEPi(bcx, val, [0u, abi::vec_elt_alloc]));
284
285 // Create a temporary scope lest execution should fail while
286 // constructing the vector.
287 let temp_scope = fcx.push_custom_cleanup_scope();
288 fcx.schedule_free_value(cleanup::CustomScope(temp_scope),
289 val, cleanup::HeapExchange);
290
291 let dataptr = get_dataptr(bcx, val);
292
293 debug!("alloc_uniq_vec() returned val={}, dataptr={}",
294 bcx.val_to_str(val), bcx.val_to_str(dataptr));
295
296 let bcx = write_content(bcx, &vt, vstore_expr,
297 content_expr, SaveIn(dataptr));
298
299 fcx.pop_custom_cleanup_scope(temp_scope);
300
301 immediate_rvalue_bcx(bcx, val, vec_ty).to_expr_datumblock()
302 }
303
304 pub fn write_content<'a>(
305 bcx: &'a Block<'a>,
306 vt: &VecTypes,
307 vstore_expr: &ast::Expr,
308 content_expr: &ast::Expr,
309 dest: Dest)
310 -> &'a Block<'a> {
311 let _icx = push_ctxt("tvec::write_content");
312 let fcx = bcx.fcx;
313 let mut bcx = bcx;
314
315 debug!("write_content(vt={}, dest={}, vstore_expr={:?})",
316 vt.to_str(bcx.ccx()),
317 dest.to_str(bcx.ccx()),
318 bcx.expr_to_str(vstore_expr));
319
320 match content_expr.node {
321 ast::ExprLit(lit) => {
322 match lit.node {
323 ast::LitStr(ref s, _) => {
324 match dest {
325 Ignore => return bcx,
326 SaveIn(lldest) => {
327 let bytes = s.get().len();
328 let llbytes = C_uint(bcx.ccx(), bytes);
329 let llcstr = C_cstr(bcx.ccx(), (*s).clone(), false);
330 base::call_memcpy(bcx,
331 lldest,
332 llcstr,
333 llbytes,
334 1);
335 return bcx;
336 }
337 }
338 }
339 _ => {
340 bcx.tcx().sess.span_bug(content_expr.span,
341 "unexpected evec content");
342 }
343 }
344 }
345 ast::ExprVec(ref elements) => {
346 match dest {
347 Ignore => {
348 for element in elements.iter() {
349 bcx = expr::trans_into(bcx, *element, Ignore);
350 }
351 }
352
353 SaveIn(lldest) => {
354 let temp_scope = fcx.push_custom_cleanup_scope();
355 for (i, element) in elements.iter().enumerate() {
356 let lleltptr = GEPi(bcx, lldest, [i]);
357 debug!("writing index {:?} with lleltptr={:?}",
358 i, bcx.val_to_str(lleltptr));
359 bcx = expr::trans_into(bcx, *element,
360 SaveIn(lleltptr));
361 fcx.schedule_drop_mem(
362 cleanup::CustomScope(temp_scope),
363 lleltptr,
364 vt.unit_ty);
365 }
366 fcx.pop_custom_cleanup_scope(temp_scope);
367 }
368 }
369 return bcx;
370 }
371 ast::ExprRepeat(element, count_expr) => {
372 match dest {
373 Ignore => {
374 return expr::trans_into(bcx, element, Ignore);
375 }
376 SaveIn(lldest) => {
377 let count = ty::eval_repeat_count(bcx.tcx(), count_expr);
378 if count == 0 {
379 return bcx;
380 }
381
382 // Some cleanup would be required in the case in which failure happens
383 // during a copy. But given that copy constructors are not overridable,
384 // this can only happen as a result of OOM. So we just skip out on the
385 // cleanup since things would *probably* be broken at that point anyways.
386
387 let elem = unpack_datum!(bcx, expr::trans(bcx, element));
388 assert!(!ty::type_moves_by_default(bcx.tcx(), elem.ty));
389
390 let bcx = iter_vec_loop(bcx, lldest, vt,
391 C_uint(bcx.ccx(), count), |set_bcx, lleltptr, _| {
392 elem.shallow_copy_and_take(set_bcx, lleltptr)
393 });
394
395 elem.add_clean_if_rvalue(bcx, element.id);
396 bcx
397 }
398 }
399 }
400 _ => {
401 bcx.tcx().sess.span_bug(content_expr.span,
402 "unexpected vec content");
403 }
404 }
405 }
406
407 pub fn vec_types_from_expr(bcx: &Block, vec_expr: &ast::Expr) -> VecTypes {
408 let vec_ty = node_id_type(bcx, vec_expr.id);
409 vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty))
410 }
411
412 pub fn vec_types(bcx: &Block, unit_ty: ty::t) -> VecTypes {
413 let ccx = bcx.ccx();
414 let llunit_ty = type_of::type_of(ccx, unit_ty);
415 let llunit_size = nonzero_llsize_of(ccx, llunit_ty);
416 let llunit_alloc_size = llsize_of_alloc(ccx, llunit_ty);
417
418 VecTypes {
419 unit_ty: unit_ty,
420 llunit_ty: llunit_ty,
421 llunit_size: llunit_size,
422 llunit_alloc_size: llunit_alloc_size
423 }
424 }
425
426 pub fn elements_required(bcx: &Block, content_expr: &ast::Expr) -> uint {
427 //! Figure out the number of elements we need to store this content
428
429 match content_expr.node {
430 ast::ExprLit(lit) => {
431 match lit.node {
432 ast::LitStr(ref s, _) => s.get().len(),
433 _ => {
434 bcx.tcx().sess.span_bug(content_expr.span,
435 "unexpected evec content")
436 }
437 }
438 },
439 ast::ExprVec(ref es) => es.len(),
440 ast::ExprRepeat(_, count_expr) => {
441 ty::eval_repeat_count(bcx.tcx(), count_expr)
442 }
443 _ => bcx.tcx().sess.span_bug(content_expr.span,
444 "unexpected vec content")
445 }
446 }
447
448 pub fn get_fixed_base_and_byte_len(bcx: &Block,
449 llval: ValueRef,
450 unit_ty: ty::t,
451 vec_length: uint)
452 -> (ValueRef, ValueRef) {
453 /*!
454 * Converts a fixed-length vector into the slice pair.
455 * The vector should be stored in `llval` which should be by ref.
456 */
457
458 let ccx = bcx.ccx();
459 let vt = vec_types(bcx, unit_ty);
460
461 let base = GEPi(bcx, llval, [0u, 0u]);
462 let len = Mul(bcx, C_uint(ccx, vec_length), vt.llunit_size);
463 (base, len)
464 }
465
466 pub fn get_base_and_len(bcx: &Block,
467 llval: ValueRef,
468 vec_ty: ty::t)
469 -> (ValueRef, ValueRef) {
470 /*!
471 * Converts a vector into the slice pair. The vector should be
472 * stored in `llval` which should be by-reference. If you have a
473 * datum, you would probably prefer to call
474 * `Datum::get_base_and_len()` which will handle any conversions
475 * for you.
476 */
477
478 let ccx = bcx.ccx();
479
480 match ty::get(vec_ty).sty {
481 ty::ty_vec(_, Some(n)) => {
482 let base = GEPi(bcx, llval, [0u, 0u]);
483 (base, C_uint(ccx, n))
484 }
485 ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
486 ty::ty_vec(_, None) | ty::ty_str => {
487 assert!(!type_is_immediate(bcx.ccx(), vec_ty));
488 let base = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_base]));
489 let count = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
490 (base, count)
491 }
492 _ => ccx.sess().bug("unexpected type (ty_rptr) in get_base_and_len"),
493 },
494 ty::ty_uniq(t) => match ty::get(t).sty {
495 ty::ty_vec(_, None) | ty::ty_str => {
496 assert!(type_is_immediate(bcx.ccx(), vec_ty));
497 let vt = vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
498 let body = Load(bcx, llval);
499 (get_dataptr(bcx, body), UDiv(bcx, get_fill(bcx, body), vt.llunit_size))
500 }
501 _ => ccx.sess().bug("unexpected type (ty_uniq) in get_base_and_len"),
502 },
503 _ => ccx.sess().bug("unexpected type in get_base_and_len"),
504 }
505 }
506
507 pub type iter_vec_block<'r,'b> =
508 |&'b Block<'b>, ValueRef, ty::t|: 'r -> &'b Block<'b>;
509
510 pub fn iter_vec_loop<'r,
511 'b>(
512 bcx: &'b Block<'b>,
513 data_ptr: ValueRef,
514 vt: &VecTypes,
515 count: ValueRef,
516 f: iter_vec_block<'r,'b>)
517 -> &'b Block<'b> {
518 let _icx = push_ctxt("tvec::iter_vec_loop");
519 let fcx = bcx.fcx;
520
521 let next_bcx = fcx.new_temp_block("expr_repeat: while next");
522 let loop_bcx = fcx.new_temp_block("expr_repeat");
523 let cond_bcx = fcx.new_temp_block("expr_repeat: loop cond");
524 let body_bcx = fcx.new_temp_block("expr_repeat: body: set");
525 let inc_bcx = fcx.new_temp_block("expr_repeat: body: inc");
526 Br(bcx, loop_bcx.llbb);
527
528 let loop_counter = {
529 // i = 0
530 let i = alloca(loop_bcx, bcx.ccx().int_type, "__i");
531 Store(loop_bcx, C_uint(bcx.ccx(), 0), i);
532
533 Br(loop_bcx, cond_bcx.llbb);
534 i
535 };
536
537 { // i < count
538 let lhs = Load(cond_bcx, loop_counter);
539 let rhs = count;
540 let cond_val = ICmp(cond_bcx, lib::llvm::IntULT, lhs, rhs);
541
542 CondBr(cond_bcx, cond_val, body_bcx.llbb, next_bcx.llbb);
543 }
544
545 { // loop body
546 let i = Load(body_bcx, loop_counter);
547 let lleltptr = if vt.llunit_alloc_size == 0 {
548 data_ptr
549 } else {
550 InBoundsGEP(body_bcx, data_ptr, [i])
551 };
552 let body_bcx = f(body_bcx, lleltptr, vt.unit_ty);
553
554 Br(body_bcx, inc_bcx.llbb);
555 }
556
557 { // i += 1
558 let i = Load(inc_bcx, loop_counter);
559 let plusone = Add(inc_bcx, i, C_uint(bcx.ccx(), 1));
560 Store(inc_bcx, plusone, loop_counter);
561
562 Br(inc_bcx, cond_bcx.llbb);
563 }
564
565 next_bcx
566 }
567
568 pub fn iter_vec_raw<'r,
569 'b>(
570 bcx: &'b Block<'b>,
571 data_ptr: ValueRef,
572 unit_ty: ty::t,
573 fill: ValueRef,
574 f: iter_vec_block<'r,'b>)
575 -> &'b Block<'b> {
576 let _icx = push_ctxt("tvec::iter_vec_raw");
577 let fcx = bcx.fcx;
578
579 let vt = vec_types(bcx, unit_ty);
580 if vt.llunit_alloc_size == 0 {
581 // Special-case vectors with elements of size 0 so they don't go out of bounds (#9890)
582 iter_vec_loop(bcx, data_ptr, &vt, fill, f)
583 } else {
584 // Calculate the last pointer address we want to handle.
585 // FIXME (#3729): Optimize this when the size of the unit type is
586 // statically known to not use pointer casts, which tend to confuse
587 // LLVM.
588 let data_end_ptr = pointer_add_byte(bcx, data_ptr, fill);
589
590 // Now perform the iteration.
591 let header_bcx = fcx.new_temp_block("iter_vec_loop_header");
592 Br(bcx, header_bcx.llbb);
593 let data_ptr =
594 Phi(header_bcx, val_ty(data_ptr), [data_ptr], [bcx.llbb]);
595 let not_yet_at_end =
596 ICmp(header_bcx, lib::llvm::IntULT, data_ptr, data_end_ptr);
597 let body_bcx = fcx.new_temp_block("iter_vec_loop_body");
598 let next_bcx = fcx.new_temp_block("iter_vec_next");
599 CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb);
600 let body_bcx = f(body_bcx, data_ptr, vt.unit_ty);
601 AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr,
602 [C_int(bcx.ccx(), 1)]),
603 body_bcx.llbb);
604 Br(body_bcx, header_bcx.llbb);
605 next_bcx
606 }
607 }
librustc/middle/trans/tvec.rs:506:1-506:1 -NK_AS_STR_TODO- definition:
pub type iter_vec_block<'r,'b> =
|&'b Block<'b>, ValueRef, ty::t|: 'r -> &'b Block<'b>;
pub fn iter_vec_loop<'r,
references:- 2573: fill: ValueRef,
574: f: iter_vec_block<'r,'b>)
575: -> &'b Block<'b> {
librustc/middle/trans/tvec.rs:411:1-411:1 -fn- definition:
pub fn vec_types(bcx: &Block, unit_ty: ty::t) -> VecTypes {
let ccx = bcx.ccx();
let llunit_ty = type_of::type_of(ccx, unit_ty);
references:- 7579: let vt = vec_types(bcx, unit_ty);
580: if vt.llunit_alloc_size == 0 {
librustc/middle/trans/_match.rs:
1012: let vec_ty = node_id_type(bcx, pat_id);
1013: let vt = tvec::vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
librustc/middle/trans/expr.rs:
481: let vt = tvec::vec_types(bcx, ty::sequence_element_type(bcx.tcx(), base_datum.ty));
482: base::maybe_name_value(bcx.ccx(), vt.llunit_size, "unit_sz");
librustc/middle/trans/tvec.rs:303:1-303:1 -fn- definition:
pub fn write_content<'a>(
bcx: &'a Block<'a>,
vt: &VecTypes,
references:- 4174: // Generate the content into the backing array.
175: bcx = write_content(bcx, &vt, vstore_expr,
176: content_expr, SaveIn(llfixed));
--
296: let bcx = write_content(bcx, &vt, vstore_expr,
297: content_expr, SaveIn(dataptr));
librustc/middle/trans/tvec.rs:406:1-406:1 -fn- definition:
pub fn vec_types_from_expr(bcx: &Block, vec_expr: &ast::Expr) -> VecTypes {
let vec_ty = node_id_type(bcx, vec_expr.id);
vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty))
references:- 2150: // Handle the &[...] case:
151: let vt = vec_types_from_expr(bcx, vstore_expr);
152: let count = elements_required(bcx, content_expr);
librustc/middle/trans/tvec.rs:567:1-567:1 -fn- definition:
pub fn iter_vec_raw<'r,
'b>(
bcx: &'b Block<'b>,
references:- 2librustc/middle/trans/base.rs:
701: let (base, len) = tvec::get_fixed_base_and_byte_len(cx, av, unit_ty, n);
702: cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f);
703: }
librustc/middle/trans/tvec.rs:
63: let dataptr = get_dataptr(bcx, vptr);
64: iter_vec_raw(bcx, dataptr, unit_ty, fill, glue::drop_ty)
65: } else { bcx }
librustc/middle/trans/tvec.rs:67:1-67:1 -struct- definition:
pub struct VecTypes {
pub unit_ty: ty::t,
pub llunit_ty: Type,
references:- 6418: VecTypes {
419: unit_ty: unit_ty,
--
513: data_ptr: ValueRef,
514: vt: &VecTypes,
515: count: ValueRef,
librustc/middle/trans/tvec.rs:465:1-465:1 -fn- definition:
pub fn get_base_and_len(bcx: &Block,
llval: ValueRef,
vec_ty: ty::t)
references:- 2librustc/middle/trans/_match.rs:
1615: let vec_ty = node_id_type(bcx, pat_id);
1616: let (_, len) = tvec::get_base_and_len(bcx, val, vec_ty);
1617: test_val = len;
librustc/middle/trans/datum.rs:
525: tvec::get_base_and_len(bcx, self.val, self.ty)
526: }
librustc/middle/trans/tvec.rs:46:1-46:1 -fn- definition:
pub fn pointer_add_byte(bcx: &Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
let _icx = push_ctxt("tvec::pointer_add_byte");
let old_ty = val_ty(ptr);
references:- 2587: // LLVM.
588: let data_end_ptr = pointer_add_byte(bcx, data_ptr, fill);
librustc/middle/trans/_match.rs:
1029: let slice_byte_offset = Mul(bcx, vt.llunit_size, C_uint(bcx.ccx(), n));
1030: let slice_begin = tvec::pointer_add_byte(bcx, base, slice_byte_offset);
1031: let slice_len_offset = C_uint(bcx.ccx(), elem_count - 1u);
librustc/middle/trans/tvec.rs:425:1-425:1 -fn- definition:
pub fn elements_required(bcx: &Block, content_expr: &ast::Expr) -> uint {
//! Figure out the number of elements we need to store this content
match content_expr.node {
references:- 2269: let vt = vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
270: let count = elements_required(bcx, content_expr);
librustc/middle/trans/tvec.rs:190:1-190:1 -fn- definition:
pub fn trans_lit_str<'a>(
bcx: &'a Block<'a>,
lit_expr: &ast::Expr,
references:- 2librustc/middle/trans/expr.rs:
685: ast::LitStr(ref s, _) => {
686: tvec::trans_lit_str(bcx, expr, (*s).clone(), dest)
687: }
librustc/middle/trans/tvec.rs:
138: ast::LitStr(ref s, _) => {
139: return trans_lit_str(bcx,
140: content_expr,
librustc/middle/trans/tvec.rs:36:1-36:1 -fn- definition:
pub fn get_fill(bcx: &Block, vptr: ValueRef) -> ValueRef {
let _icx = push_ctxt("tvec::get_fill");
Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_fill]))
references:- 2498: let body = Load(bcx, llval);
499: (get_dataptr(bcx, body), UDiv(bcx, get_fill(bcx, body), vt.llunit_size))
500: }
librustc/middle/trans/tvec.rs:41:1-41:1 -fn- definition:
pub fn get_dataptr(bcx: &Block, vptr: ValueRef) -> ValueRef {
let _icx = push_ctxt("tvec::get_dataptr");
GEPi(bcx, vptr, [0u, abi::vec_elt_elems, 0u])
references:- 3291: let dataptr = get_dataptr(bcx, val);
--
498: let body = Load(bcx, llval);
499: (get_dataptr(bcx, body), UDiv(bcx, get_fill(bcx, body), vt.llunit_size))
500: }
librustc/middle/trans/tvec.rs:53:1-53:1 -fn- definition:
pub fn make_drop_glue_unboxed<'a>(
bcx: &'a Block<'a>,
vptr: ValueRef,
references:- 2librustc/middle/trans/glue.rs:
293: let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
294: let bcx = tvec::make_drop_glue_unboxed(bcx, llbox, unit_ty);
295: trans_exchange_free(bcx, llbox)
librustc/middle/trans/tvec.rs:509:1-509:1 -fn- definition:
pub fn iter_vec_loop<'r,
'b>(
bcx: &'b Block<'b>,
references:- 2390: let bcx = iter_vec_loop(bcx, lldest, vt,
391: C_uint(bcx.ccx(), count), |set_bcx, lleltptr, _| {
--
581: // Special-case vectors with elements of size 0 so they don't go out of bounds (#9890)
582: iter_vec_loop(bcx, data_ptr, &vt, fill, f)
583: } else {