diff options
| author | Jed Davis <jld@panix.com> | 2013-01-08 00:24:43 -0800 |
|---|---|---|
| committer | Tim Chevalier <chevalier@alum.wellesley.edu> | 2013-01-13 14:37:59 -0800 |
| commit | 1b01629f189f1c4050bd5c7eac81e44ba2c7a76f (patch) | |
| tree | a958ba05b82b2948ca24891931c704f69ad9014f | |
| parent | ea53c48ca23ec4e46454d48936c209d2a67cf892 (diff) | |
Make vectors (& old ports) of zero-size types allocate one byte each.
| -rw-r--r-- | src/libcore/oldcomm.rs | 3 | ||||
| -rw-r--r-- | src/libcore/sys.rs | 21 | ||||
| -rw-r--r-- | src/libcore/vec.rs | 32 | ||||
| -rw-r--r-- | src/librustc/middle/trans/machine.rs | 11 | ||||
| -rw-r--r-- | src/librustc/middle/trans/tvec.rs | 7 |
5 files changed, 59 insertions, 15 deletions
diff --git a/src/libcore/oldcomm.rs b/src/libcore/oldcomm.rs index 65aaf1fe428..ae3116b08f0 100644 --- a/src/libcore/oldcomm.rs +++ b/src/libcore/oldcomm.rs @@ -91,7 +91,8 @@ pub enum Chan<T: Owned> { /// Constructs a port pub fn Port<T: Owned>() -> Port<T> { unsafe { - Port_(@PortPtr(rustrt::new_port(sys::size_of::<T>() as size_t))) + Port_(@PortPtr(rustrt::new_port(sys::nonzero_size_of::<T>() + as size_t))) } } diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index ad9c3d1e51d..322aa895eb4 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -88,6 +88,17 @@ pub pure fn size_of<T>() -> uint { } /** + * Returns the size of a type, or 1 if the actual size is zero. + * + * Useful for building structures containing variable-length arrays. + */ +#[inline(always)] +pub pure fn nonzero_size_of<T>() -> uint { + let s = size_of::<T>(); + if s == 0 { 1 } else { s } +} + +/** * Returns the ABI-required minimum alignment of a type * * This is the alignment used for struct fields. It may be smaller @@ -146,7 +157,7 @@ pub pure fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { #[cfg(test)] pub mod tests { use cast; - use sys::{Closure, pref_align_of, size_of}; + use sys::{Closure, pref_align_of, size_of, nonzero_size_of}; #[test] pub fn size_of_basic() { @@ -172,6 +183,14 @@ pub mod tests { } #[test] + pub fn nonzero_size_of_basic() { + type Z = [i8 * 0]; + assert size_of::<Z>() == 0u; + assert nonzero_size_of::<Z>() == 1u; + assert nonzero_size_of::<uint>() == size_of::<uint>(); + } + + #[test] pub fn align_of_basic() { assert pref_align_of::<u8>() == 1u; assert pref_align_of::<u16>() == 2u; diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index b9cefa89aa7..29767f3c1e0 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -103,7 +103,7 @@ pub fn reserve_at_least<T>(v: &mut ~[T], n: uint) { pub pure fn capacity<T>(v: &const ~[T]) -> uint { unsafe { let repr: **raw::VecRepr = ::cast::transmute(v); - (**repr).unboxed.alloc / sys::size_of::<T>() + (**repr).unboxed.alloc / sys::nonzero_size_of::<T>() } } @@ -276,7 +276,7 @@ pub pure fn view<T>(v: &r/[T], start: uint, end: uint) -> &r/[T] { unsafe { ::cast::reinterpret_cast( &(ptr::offset(p, start), - (end - start) * sys::size_of::<T>())) + (end - start) * sys::nonzero_size_of::<T>())) } } } @@ -289,7 +289,7 @@ pub pure fn mut_view<T>(v: &r/[mut T], start: uint, end: uint) -> &r/[mut T] { unsafe { ::cast::reinterpret_cast( &(ptr::mut_offset(p, start), - (end - start) * sys::size_of::<T>())) + (end - start) * sys::nonzero_size_of::<T>())) } } } @@ -303,7 +303,7 @@ pub pure fn const_view<T>(v: &r/[const T], start: uint, unsafe { ::cast::reinterpret_cast( &(ptr::const_offset(p, start), - (end - start) * sys::size_of::<T>())) + (end - start) * sys::nonzero_size_of::<T>())) } } } @@ -608,7 +608,7 @@ pub fn push<T>(v: &mut ~[T], initval: T) { unsafe fn push_fast<T>(v: &mut ~[T], initval: T) { let repr: **raw::VecRepr = ::cast::transmute(v); let fill = (**repr).unboxed.fill; - (**repr).unboxed.fill += sys::size_of::<T>(); + (**repr).unboxed.fill += sys::nonzero_size_of::<T>(); let p = addr_of(&((**repr).unboxed.data)); let p = ptr::offset(p, fill) as *mut T; rusti::move_val_init(&mut(*p), move initval); @@ -1449,7 +1449,7 @@ pub pure fn as_imm_buf<T,U>(s: &[T], let v : *(*T,uint) = ::cast::reinterpret_cast(&addr_of(&s)); let (buf,len) = *v; - f(buf, len / sys::size_of::<T>()) + f(buf, len / sys::nonzero_size_of::<T>()) } } @@ -1462,7 +1462,7 @@ pub pure fn as_const_buf<T,U>(s: &[const T], let v : *(*const T,uint) = ::cast::reinterpret_cast(&addr_of(&s)); let (buf,len) = *v; - f(buf, len / sys::size_of::<T>()) + f(buf, len / sys::nonzero_size_of::<T>()) } } @@ -1475,7 +1475,7 @@ pub pure fn as_mut_buf<T,U>(s: &[mut T], let v : *(*mut T,uint) = ::cast::reinterpret_cast(&addr_of(&s)); let (buf,len) = *v; - f(buf, len / sys::size_of::<T>()) + f(buf, len / sys::nonzero_size_of::<T>()) } } @@ -1992,7 +1992,7 @@ pub mod raw { #[inline(always)] pub unsafe fn set_len<T>(v: &mut ~[T], new_len: uint) { let repr: **VecRepr = ::cast::transmute(v); - (**repr).unboxed.fill = new_len * sys::size_of::<T>(); + (**repr).unboxed.fill = new_len * sys::nonzero_size_of::<T>(); } /** @@ -2032,7 +2032,7 @@ pub mod raw { pub unsafe fn buf_as_slice<T,U>(p: *T, len: uint, f: fn(v: &[T]) -> U) -> U { - let pair = (p, len * sys::size_of::<T>()); + let pair = (p, len * sys::nonzero_size_of::<T>()); let v : *(&blk/[T]) = ::cast::reinterpret_cast(&addr_of(&pair)); f(*v) @@ -2502,6 +2502,18 @@ mod tests { } #[test] + fn test_len_divzero() { + type Z = [i8 * 0]; + let v0 : &[Z] = &[]; + let v1 : &[Z] = &[[]]; + let v2 : &[Z] = &[[], []]; + assert(sys::size_of::<Z>() == 0); + assert(len(v0) == 0); + assert(len(v1) == 1); + assert(len(v2) == 2); + } + + #[test] fn test_head() { let a = ~[11, 12]; assert (head(a) == 11); diff --git a/src/librustc/middle/trans/machine.rs b/src/librustc/middle/trans/machine.rs index 0e778e2d705..bc1cd5ec911 100644 --- a/src/librustc/middle/trans/machine.rs +++ b/src/librustc/middle/trans/machine.rs @@ -132,6 +132,17 @@ pub fn llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef { } } +// Returns the "default" size of t (see above), or 1 if the size would +// be zero. This is important for things like vectors that expect +// space to be consumed. +pub fn nonzero_llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef { + if llbitsize_of_real(cx, t) == 0 { + unsafe { llvm::LLVMConstInt(cx.int_type, 1, False) } + } else { + llsize_of(cx, t) + } +} + // Returns the preferred alignment of the given type for the current target. // The preffered alignment may be larger than the alignment used when // packing the type into structs. This will be used for things like diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index e85b7fe14dc..9db607773eb 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -17,7 +17,7 @@ use middle::trans::datum::*; use middle::trans::expr::{Dest, Ignore, SaveIn}; use middle::trans::expr; use middle::trans::glue; -use middle::trans::shape::llsize_of; +use middle::trans::shape::{llsize_of, nonzero_llsize_of}; use middle::trans::type_of; use middle::ty; use util::common::indenter; @@ -96,7 +96,7 @@ fn alloc_vec(bcx: block, unit_ty: ty::t, elts: uint, heap: heap) -> Result { let _icx = bcx.insn_ctxt("tvec::alloc_uniq"); let ccx = bcx.ccx(); let llunitty = type_of::type_of(ccx, unit_ty); - let unit_sz = llsize_of(ccx, llunitty); + let unit_sz = nonzero_llsize_of(ccx, llunitty); let fill = Mul(bcx, C_uint(ccx, elts), unit_sz); let alloc = if elts < 4u { Mul(bcx, C_int(ccx, 4), unit_sz) } @@ -418,7 +418,8 @@ fn vec_types(bcx: block, vec_ty: ty::t) -> VecTypes { let ccx = bcx.ccx(); let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty); let llunit_ty = type_of::type_of(ccx, unit_ty); - let llunit_size = llsize_of(ccx, llunit_ty); + let llunit_size = nonzero_llsize_of(ccx, llunit_ty); + VecTypes {vec_ty: vec_ty, unit_ty: unit_ty, llunit_ty: llunit_ty, |
