Make vectors (& old ports) of zero-size types allocate one byte each.

This commit is contained in:
Jed Davis 2013-01-08 00:24:43 -08:00 committed by Tim Chevalier
parent ea53c48ca2
commit 1b01629f18
5 changed files with 59 additions and 15 deletions

View File

@ -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)))
}
}

View File

@ -87,6 +87,17 @@ pub pure fn size_of<T>() -> uint {
unsafe { rusti::size_of::<T>() }
}
/**
* 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
*
@ -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() {
@ -171,6 +182,14 @@ pub mod tests {
assert size_of::<*uint>() == 8u;
}
#[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;

View File

@ -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)
@ -2501,6 +2501,18 @@ mod tests {
assert (!is_not_empty::<int>(~[]));
}
#[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];

View File

@ -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

View File

@ -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,