Make vectors (& old ports) of zero-size types allocate one byte each.
This commit is contained in:
parent
ea53c48ca2
commit
1b01629f18
@ -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)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user