(index<- )        ./librustc/middle/trans/tvec.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   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, vptrValueRef) -> 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, vptrValueRef) -> 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, ptrValueRef, bytesValueRef) -> 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                                vptrValueRef,
  57                                unit_tyty::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                            destexpr::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                            destexpr::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_litInternedString,
 195                       destDest)
 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                       destDest)
 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_tyty::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                                     llvalValueRef,
 450                                     unit_tyty::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                          llvalValueRef,
 468                          vec_tyty::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_ptrValueRef,
 514                       vt: &VecTypes,
 515                       countValueRef,
 516                       fiter_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_ptrValueRef,
 572                      unit_tyty::t,
 573                      fillValueRef,
 574                      fiter_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:- 2
573:                     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:- 7
579:     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:- 4
174:         // 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:- 2
150:     // 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:- 2
librustc/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:- 6
418:     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:- 2
librustc/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:- 2
587:         // 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:- 2
269:     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:- 2
librustc/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:- 2
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: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:- 3
291:     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:- 2
librustc/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:- 2
390:                     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 {