]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/tvec.rs
Rollup merge of #35911 - tbu-:pr_io_errorkind_traits, r=alexcrichton
[rust.git] / src / librustc_trans / tvec.rs
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 llvm;
14 use llvm::ValueRef;
15 use base::*;
16 use build::*;
17 use common::*;
18 use debuginfo::DebugLoc;
19 use rustc::ty::Ty;
20
21 pub fn slice_for_each<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
22                                      data_ptr: ValueRef,
23                                      unit_ty: Ty<'tcx>,
24                                      len: ValueRef,
25                                      f: F)
26                                      -> Block<'blk, 'tcx> where
27     F: FnOnce(Block<'blk, 'tcx>, ValueRef) -> Block<'blk, 'tcx>,
28 {
29     let _icx = push_ctxt("tvec::slice_for_each");
30     let fcx = bcx.fcx;
31
32     // Special-case vectors with elements of size 0  so they don't go out of bounds (#9890)
33     let zst = type_is_zero_size(bcx.ccx(), unit_ty);
34     let add = |bcx, a, b| if zst {
35         Add(bcx, a, b, DebugLoc::None)
36     } else {
37         InBoundsGEP(bcx, a, &[b])
38     };
39
40     let header_bcx = fcx.new_block("slice_loop_header");
41     let body_bcx = fcx.new_block("slice_loop_body");
42     let next_bcx = fcx.new_block("slice_loop_next");
43
44     let start = if zst {
45         C_uint(bcx.ccx(), 0 as usize)
46     } else {
47         data_ptr
48     };
49     let end = add(bcx, start, len);
50
51     Br(bcx, header_bcx.llbb, DebugLoc::None);
52     let current = Phi(header_bcx, val_ty(start), &[start], &[bcx.llbb]);
53
54     let keep_going =
55         ICmp(header_bcx, llvm::IntULT, current, end, DebugLoc::None);
56     CondBr(header_bcx, keep_going, body_bcx.llbb, next_bcx.llbb, DebugLoc::None);
57
58     let body_bcx = f(body_bcx, if zst { data_ptr } else { current });
59     let next = add(body_bcx, current, C_uint(bcx.ccx(), 1usize));
60     AddIncomingToPhi(current, next, body_bcx.llbb);
61     Br(body_bcx, header_bcx.llbb, DebugLoc::None);
62     next_bcx
63 }