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

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Sat Feb 15 17:22:38 2014
   1  // Copyright 2012-2013 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  // Information concerning the machine representation of various types.
  12  
  13  use lib::llvm::{ValueRef};
  14  use lib::llvm::False;
  15  use lib::llvm::llvm;
  16  use middle::trans::common::*;
  17  
  18  use middle::trans::type_::Type;
  19  
  20  // ______________________________________________________________________
  21  // compute sizeof / alignof
  22  
  23  // Returns the number of bytes clobbered by a Store to this type.
  24  pub fn llsize_of_store(cx: &CrateContext, tyType) -> u64 {
  25      unsafe {
  26          return llvm::LLVMStoreSizeOfType(cx.td.lltd, ty.to_ref()) as u64;
  27      }
  28  }
  29  
  30  // Returns the number of bytes between successive elements of type T in an
  31  // array of T. This is the "ABI" size. It includes any ABI-mandated padding.
  32  pub fn llsize_of_alloc(cx: &CrateContext, tyType) -> u64 {
  33      unsafe {
  34          return llvm::LLVMABISizeOfType(cx.td.lltd, ty.to_ref()) as u64;
  35      }
  36  }
  37  
  38  // Returns, as near as we can figure, the "real" size of a type. As in, the
  39  // bits in this number of bytes actually carry data related to the datum
  40  // with the type. Not junk, padding, accidentally-damaged words, or
  41  // whatever. Rounds up to the nearest byte though, so if you have a 1-bit
  42  // value, we return 1 here, not 0. Most of rustc works in bytes. Be warned
  43  // that LLVM *does* distinguish between e.g. a 1-bit value and an 8-bit value
  44  // at the codegen level! In general you should prefer `llbitsize_of_real`
  45  // below.
  46  pub fn llsize_of_real(cx: &CrateContext, tyType) -> u64 {
  47      unsafe {
  48          let nbits = llvm::LLVMSizeOfTypeInBits(cx.td.lltd, ty.to_ref()) as u64;
  49          if nbits & 7 != 0 {
  50              // Not an even number of bytes, spills into "next" byte.
  51              1 + (nbits >> 3)
  52          } else {
  53              nbits >> 3
  54          }
  55      }
  56  }
  57  
  58  /// Returns the "real" size of the type in bits.
  59  pub fn llbitsize_of_real(cx: &CrateContext, tyType) -> u64 {
  60      unsafe {
  61          llvm::LLVMSizeOfTypeInBits(cx.td.lltd, ty.to_ref()) as u64
  62      }
  63  }
  64  
  65  /// Returns the size of the type as an LLVM constant integer value.
  66  pub fn llsize_of(cx: &CrateContext, tyType) -> ValueRef {
  67      // Once upon a time, this called LLVMSizeOf, which does a
  68      // getelementptr(1) on a null pointer and casts to an int, in
  69      // order to obtain the type size as a value without requiring the
  70      // target data layout.  But we have the target data layout, so
  71      // there's no need for that contrivance.  The instruction
  72      // selection DAG generator would flatten that GEP(1) node into a
  73      // constant of the type's alloc size, so let's save it some work.
  74      return C_uint(cx, llsize_of_alloc(cx, ty) as uint);
  75  }
  76  
  77  // Returns the "default" size of t (see above), or 1 if the size would
  78  // be zero.  This is important for things like vectors that expect
  79  // space to be consumed.
  80  pub fn nonzero_llsize_of(cx: &CrateContext, tyType) -> ValueRef {
  81      if llbitsize_of_real(cx, ty) == 0 {
  82          unsafe { llvm::LLVMConstInt(cx.int_type.to_ref(), 1, False) }
  83      } else {
  84          llsize_of(cx, ty)
  85      }
  86  }
  87  
  88  // Returns the preferred alignment of the given type for the current target.
  89  // The preferred alignment may be larger than the alignment used when
  90  // packing the type into structs. This will be used for things like
  91  // allocations inside a stack frame, which LLVM has a free hand in.
  92  pub fn llalign_of_pref(cx: &CrateContext, tyType) -> u64 {
  93      unsafe {
  94          return llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, ty.to_ref()) as u64;
  95      }
  96  }
  97  
  98  // Returns the minimum alignment of a type required by the platform.
  99  // This is the alignment that will be used for struct fields, arrays,
 100  // and similar ABI-mandated things.
 101  pub fn llalign_of_min(cx: &CrateContext, tyType) -> u64 {
 102      unsafe {
 103          return llvm::LLVMABIAlignmentOfType(cx.td.lltd, ty.to_ref()) as u64;
 104      }
 105  }
 106  
 107  // Returns the "default" alignment of t, which is calculated by casting
 108  // null to a record containing a single-bit followed by a t value, then
 109  // doing gep(0,1) to get at the trailing (and presumably padded) t cell.
 110  pub fn llalign_of(cx: &CrateContext, tyType) -> ValueRef {
 111      unsafe {
 112          return llvm::LLVMConstIntCast(
 113              llvm::LLVMAlignOf(ty.to_ref()), cx.int_type.to_ref(), False);
 114      }
 115  }
 116  
 117  pub fn llelement_offset(cx: &CrateContext, struct_tyType, element: uint) -> u64 {
 118      unsafe {
 119          return llvm::LLVMOffsetOfElement(cx.td.lltd, struct_ty.to_ref(), element as u32) as u64;
 120      }
 121  }


librustc/middle/trans/machine.rs:116:1-116:1 -fn- definition:
pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: uint) -> u64 {
    unsafe {
        return llvm::LLVMOffsetOfElement(cx.td.lltd, struct_ty.to_ref(), element as u32) as u64;
references:- 2
librustc/middle/trans/debuginfo.rs:
446:     let llvm_env_data_type = type_of::type_of(cx, env_data_type);
447:     let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index);
--
1781:                 FixedMemberOffset { bytes } => bytes as u64,
1782:                 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1783:             };


librustc/middle/trans/machine.rs:58:49-58:49 -fn- definition:
/// Returns the "real" size of the type in bits.
pub fn llbitsize_of_real(cx: &CrateContext, ty: Type) -> u64 {
    unsafe {
references:- 8
80: pub fn nonzero_llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
81:     if llbitsize_of_real(cx, ty) == 0 {
82:         unsafe { llvm::LLVMConstInt(cx.int_type.to_ref(), 1, False) }
librustc/middle/trans/adt.rs:
554:     assert_eq!(val_ty(ptr), llty.ptr_to());
555:     let bits = machine::llbitsize_of_real(bcx.ccx(), llty);
556:     assert!(bits <= 64);
librustc/middle/trans/expr.rs:
467:     let ix_size = machine::llbitsize_of_real(bcx.ccx(), val_ty(ix_val));
468:     let int_size = machine::llbitsize_of_real(bcx.ccx(), ccx.int_type);
469:     let ix_val = {
librustc/middle/trans/intrinsic.rs:
136:         let size = machine::llsize_of(ccx, lltp_ty);
137:         let int_size = machine::llbitsize_of_real(ccx, ccx.int_type);
138:         let name = if allow_overlap {
--
166:         let size = machine::llsize_of(ccx, lltp_ty);
167:         let name = if machine::llbitsize_of_real(ccx, ccx.int_type) == 32 {
168:             "llvm.memset.p0i8.i32"
--
384:             let in_type_size = machine::llbitsize_of_real(ccx, llintype);
385:             let out_type_size = machine::llbitsize_of_real(ccx, llouttype);
386:             if in_type_size != out_type_size {


librustc/middle/trans/machine.rs:45:10-45:10 -fn- definition:
// below.
pub fn llsize_of_real(cx: &CrateContext, ty: Type) -> u64 {
    unsafe {
references:- 3
librustc/middle/trans/intrinsic.rs:
299:             let lltp_ty = type_of::type_of(ccx, tp_ty);
300:             Ret(bcx, C_uint(ccx, machine::llsize_of_real(ccx, lltp_ty) as uint));
301:         }
librustc/middle/trans/reflect.rs:
68:         let tr = type_of(self.bcx.ccx(), t);
69:         let s = machine::llsize_of_real(self.bcx.ccx(), tr);
70:         let a = machine::llalign_of_min(self.bcx.ccx(), tr);
librustc/middle/trans/glue.rs:
407:     if ccx.sess().count_type_sizes() {
408:         println!("{}\t{}", llsize_of_real(ccx, llty),
409:                  ppaux::ty_to_str(ccx.tcx(), t));


librustc/middle/trans/machine.rs:31:77-31:77 -fn- definition:
// array of T. This is the "ABI" size. It includes any ABI-mandated padding.
pub fn llsize_of_alloc(cx: &CrateContext, ty: Type) -> u64 {
    unsafe {
references:- 17
73:     // constant of the type's alloc size, so let's save it some work.
74:     return C_uint(cx, llsize_of_alloc(cx, ty) as uint);
75: }
librustc/middle/trans/adt.rs:
796:         offsets.push(offset);
797:         offset += machine::llsize_of_alloc(ccx, llty) as u64;
798:     }
--
833:         cfields.push(val);
834:         offset += machine::llsize_of_alloc(ccx, val_ty(val)) as u64;
835:     }
librustc/middle/trans/glue.rs:
92:                     // returned for `Box<ZeroSizeType>`.
93:                     if llsize_of_alloc(ccx, llty) == 0 {
94:                         ty::mk_i8()
librustc/middle/trans/expr.rs:
1179:     // `Box<ZeroSizeType>`.
1180:     let bcx = if llsize_of_alloc(bcx.ccx(), llty) == 0 {
1181:         trans_into(bcx, contents, SaveIn(val))
librustc/middle/trans/common.rs:
88:     let llty = sizing_type_of(ccx, ty);
89:     llsize_of_alloc(ccx, llty) == 0
90: }
librustc/middle/trans/consts.rs:
273:     let llty = type_of::sizing_type_of(cx, ety_adjusted);
274:     let csize = machine::llsize_of_alloc(cx, val_ty(llconst));
275:     let tsize = machine::llsize_of_alloc(cx, llty);
276:     if csize != tsize {
librustc/middle/trans/tvec.rs:
415:     let llunit_size = nonzero_llsize_of(ccx, llunit_ty);
416:     let llunit_alloc_size = llsize_of_alloc(ccx, llunit_ty);
librustc/middle/trans/cabi_x86.rs:
67:             Struct => {
68:                 let size = llsize_of_alloc(ccx, t);
69:                 if size == 0 {
librustc/middle/trans/debuginfo.rs:
2329: fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2330:     (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2331: }
librustc/middle/trans/common.rs:
74:             let llty = sizing_type_of(ccx, ty);
75:             llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type)
76:         }


librustc/middle/trans/machine.rs:100:36-100:36 -fn- definition:
// and similar ABI-mandated things.
pub fn llalign_of_min(cx: &CrateContext, ty: Type) -> u64 {
    unsafe {
references:- 15
librustc/middle/trans/adt.rs:
823:         if !st.packed {
824:             let val_align = machine::llalign_of_min(ccx, val_ty(val))
825:                 /*bad*/as u64;
librustc/middle/trans/base.rs:
1032:         let llsz = llsize_of(ccx, llty);
1033:         let llalign = llalign_of_min(ccx, llty);
1034:         call_memcpy(bcx, dst, src, llsz, llalign as u32);
librustc/middle/trans/foreign.rs:
420:             let llrust_size = machine::llsize_of_store(ccx, llrust_ret_ty);
421:             let llforeign_align = machine::llalign_of_min(ccx, llforeign_ret_ty);
422:             let llrust_align = machine::llalign_of_min(ccx, llrust_ret_ty);
423:             let llalign = cmp::min(llforeign_align, llrust_align);
librustc/middle/trans/intrinsic.rs:
164:         let lltp_ty = type_of::type_of(ccx, tp_ty);
165:         let align = C_i32(ccx, machine::llalign_of_min(ccx, lltp_ty) as i32);
166:         let size = machine::llsize_of(ccx, lltp_ty);
--
318:             let lltp_ty = type_of::type_of(ccx, tp_ty);
319:             Ret(bcx, C_uint(ccx, machine::llalign_of_min(ccx, lltp_ty) as uint));
320:         }
librustc/middle/trans/reflect.rs:
69:         let s = machine::llsize_of_real(self.bcx.ccx(), tr);
70:         let a = machine::llalign_of_min(self.bcx.ccx(), tr);
71:         return vec!(self.c_uint(s as uint),
librustc/middle/trans/debuginfo.rs:
2329: fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2330:     (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2331: }
librustc/middle/trans/base.rs:
1066:     let size = machine::llsize_of(ccx, ty);
1067:     let align = C_i32(ccx, llalign_of_min(ccx, ty) as i32);
1068:     let volatile = C_i1(ccx, false);


librustc/middle/trans/machine.rs:91:68-91:68 -fn- definition:
// allocations inside a stack frame, which LLVM has a free hand in.
pub fn llalign_of_pref(cx: &CrateContext, ty: Type) -> u64 {
    unsafe {
references:- 3
librustc/middle/trans/builder.rs:
520:             let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
521:             let align = llalign_of_pref(self.ccx, ty.element_type());
522:             llvm::LLVMBuildAtomicStore(self.llbuilder, val, ptr, order, align as c_uint);
librustc/middle/trans/intrinsic.rs:
323:             let lltp_ty = type_of::type_of(ccx, tp_ty);
324:             Ret(bcx, C_uint(ccx, machine::llalign_of_pref(ccx, lltp_ty) as uint));
325:         }
librustc/middle/trans/builder.rs:
464:             let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
465:             let align = llalign_of_pref(self.ccx, ty.element_type());
466:             llvm::LLVMBuildAtomicLoad(self.llbuilder, ptr, noname(), order,


librustc/middle/trans/machine.rs:65:68-65:68 -fn- definition:
/// Returns the size of the type as an LLVM constant integer value.
pub fn llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
    // Once upon a time, this called LLVMSizeOf, which does a
references:- 11
83:     } else {
84:         llsize_of(cx, ty)
85:     }
librustc/middle/trans/glue.rs:
412:     let llsize = llsize_of(ccx, llty);
413:     let llalign = llalign_of(ccx, llty);
librustc/middle/trans/expr.rs:
1171:     let llty = type_of::type_of(bcx.ccx(), contents_ty);
1172:     let size = llsize_of(bcx.ccx(), llty);
1173:     // We need to a make a pointer type because box_ty is ty_bot
--
1201:     let Result {bcx, val: bx} = malloc_raw_dyn_managed(bcx, contents_ty, MallocFnLangItem,
1202:                                                         llsize_of(bcx.ccx(), ty));
1203:     let body = GEPi(bcx, bx, [0u, abi::box_field_body]);
librustc/middle/trans/base.rs:
1031:         let llty = type_of::type_of(ccx, t);
1032:         let llsz = llsize_of(ccx, llty);
1033:         let llalign = llalign_of_min(ccx, llty);
--
1065:     let llzeroval = C_u8(ccx, 0);
1066:     let size = machine::llsize_of(ccx, ty);
1067:     let align = C_i32(ccx, llalign_of_min(ccx, ty) as i32);
librustc/middle/trans/closure.rs:
146:             let ty = type_of(bcx.ccx(), cdata_ty);
147:             let size = llsize_of(bcx.ccx(), ty);
148:             // we treat proc as @ here, which isn't ideal
librustc/middle/trans/tvec.rs:
279:     let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type));
librustc/middle/trans/intrinsic.rs:
438:                     let llsize = llsize_of(ccx, llintype);
439:                     call_memcpy(bcx, lldestptr, llsrcptr, llsize, 1);


librustc/middle/trans/machine.rs:79:25-79:25 -fn- definition:
// space to be consumed.
pub fn nonzero_llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
    if llbitsize_of_real(cx, ty) == 0 {
references:- 2
librustc/middle/trans/tvec.rs:
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);