Skip to content

Commit 1b01629

Browse files
jldcatamorphism
authored andcommitted
Make vectors (& old ports) of zero-size types allocate one byte each.
1 parent ea53c48 commit 1b01629

File tree

5 files changed

+59
-15
lines changed

5 files changed

+59
-15
lines changed

src/libcore/oldcomm.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ pub enum Chan<T: Owned> {
9191
/// Constructs a port
9292
pub fn Port<T: Owned>() -> Port<T> {
9393
unsafe {
94-
Port_(@PortPtr(rustrt::new_port(sys::size_of::<T>() as size_t)))
94+
Port_(@PortPtr(rustrt::new_port(sys::nonzero_size_of::<T>()
95+
as size_t)))
9596
}
9697
}
9798

src/libcore/sys.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ pub pure fn size_of<T>() -> uint {
8787
unsafe { rusti::size_of::<T>() }
8888
}
8989

90+
/**
91+
* Returns the size of a type, or 1 if the actual size is zero.
92+
*
93+
* Useful for building structures containing variable-length arrays.
94+
*/
95+
#[inline(always)]
96+
pub pure fn nonzero_size_of<T>() -> uint {
97+
let s = size_of::<T>();
98+
if s == 0 { 1 } else { s }
99+
}
100+
90101
/**
91102
* Returns the ABI-required minimum alignment of a type
92103
*
@@ -146,7 +157,7 @@ pub pure fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
146157
#[cfg(test)]
147158
pub mod tests {
148159
use cast;
149-
use sys::{Closure, pref_align_of, size_of};
160+
use sys::{Closure, pref_align_of, size_of, nonzero_size_of};
150161

151162
#[test]
152163
pub fn size_of_basic() {
@@ -171,6 +182,14 @@ pub mod tests {
171182
assert size_of::<*uint>() == 8u;
172183
}
173184

185+
#[test]
186+
pub fn nonzero_size_of_basic() {
187+
type Z = [i8 * 0];
188+
assert size_of::<Z>() == 0u;
189+
assert nonzero_size_of::<Z>() == 1u;
190+
assert nonzero_size_of::<uint>() == size_of::<uint>();
191+
}
192+
174193
#[test]
175194
pub fn align_of_basic() {
176195
assert pref_align_of::<u8>() == 1u;

src/libcore/vec.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ pub fn reserve_at_least<T>(v: &mut ~[T], n: uint) {
103103
pub pure fn capacity<T>(v: &const ~[T]) -> uint {
104104
unsafe {
105105
let repr: **raw::VecRepr = ::cast::transmute(v);
106-
(**repr).unboxed.alloc / sys::size_of::<T>()
106+
(**repr).unboxed.alloc / sys::nonzero_size_of::<T>()
107107
}
108108
}
109109

@@ -276,7 +276,7 @@ pub pure fn view<T>(v: &r/[T], start: uint, end: uint) -> &r/[T] {
276276
unsafe {
277277
::cast::reinterpret_cast(
278278
&(ptr::offset(p, start),
279-
(end - start) * sys::size_of::<T>()))
279+
(end - start) * sys::nonzero_size_of::<T>()))
280280
}
281281
}
282282
}
@@ -289,7 +289,7 @@ pub pure fn mut_view<T>(v: &r/[mut T], start: uint, end: uint) -> &r/[mut T] {
289289
unsafe {
290290
::cast::reinterpret_cast(
291291
&(ptr::mut_offset(p, start),
292-
(end - start) * sys::size_of::<T>()))
292+
(end - start) * sys::nonzero_size_of::<T>()))
293293
}
294294
}
295295
}
@@ -303,7 +303,7 @@ pub pure fn const_view<T>(v: &r/[const T], start: uint,
303303
unsafe {
304304
::cast::reinterpret_cast(
305305
&(ptr::const_offset(p, start),
306-
(end - start) * sys::size_of::<T>()))
306+
(end - start) * sys::nonzero_size_of::<T>()))
307307
}
308308
}
309309
}
@@ -608,7 +608,7 @@ pub fn push<T>(v: &mut ~[T], initval: T) {
608608
unsafe fn push_fast<T>(v: &mut ~[T], initval: T) {
609609
let repr: **raw::VecRepr = ::cast::transmute(v);
610610
let fill = (**repr).unboxed.fill;
611-
(**repr).unboxed.fill += sys::size_of::<T>();
611+
(**repr).unboxed.fill += sys::nonzero_size_of::<T>();
612612
let p = addr_of(&((**repr).unboxed.data));
613613
let p = ptr::offset(p, fill) as *mut T;
614614
rusti::move_val_init(&mut(*p), move initval);
@@ -1449,7 +1449,7 @@ pub pure fn as_imm_buf<T,U>(s: &[T],
14491449
let v : *(*T,uint) =
14501450
::cast::reinterpret_cast(&addr_of(&s));
14511451
let (buf,len) = *v;
1452-
f(buf, len / sys::size_of::<T>())
1452+
f(buf, len / sys::nonzero_size_of::<T>())
14531453
}
14541454
}
14551455

@@ -1462,7 +1462,7 @@ pub pure fn as_const_buf<T,U>(s: &[const T],
14621462
let v : *(*const T,uint) =
14631463
::cast::reinterpret_cast(&addr_of(&s));
14641464
let (buf,len) = *v;
1465-
f(buf, len / sys::size_of::<T>())
1465+
f(buf, len / sys::nonzero_size_of::<T>())
14661466
}
14671467
}
14681468

@@ -1475,7 +1475,7 @@ pub pure fn as_mut_buf<T,U>(s: &[mut T],
14751475
let v : *(*mut T,uint) =
14761476
::cast::reinterpret_cast(&addr_of(&s));
14771477
let (buf,len) = *v;
1478-
f(buf, len / sys::size_of::<T>())
1478+
f(buf, len / sys::nonzero_size_of::<T>())
14791479
}
14801480
}
14811481

@@ -1992,7 +1992,7 @@ pub mod raw {
19921992
#[inline(always)]
19931993
pub unsafe fn set_len<T>(v: &mut ~[T], new_len: uint) {
19941994
let repr: **VecRepr = ::cast::transmute(v);
1995-
(**repr).unboxed.fill = new_len * sys::size_of::<T>();
1995+
(**repr).unboxed.fill = new_len * sys::nonzero_size_of::<T>();
19961996
}
19971997

19981998
/**
@@ -2032,7 +2032,7 @@ pub mod raw {
20322032
pub unsafe fn buf_as_slice<T,U>(p: *T,
20332033
len: uint,
20342034
f: fn(v: &[T]) -> U) -> U {
2035-
let pair = (p, len * sys::size_of::<T>());
2035+
let pair = (p, len * sys::nonzero_size_of::<T>());
20362036
let v : *(&blk/[T]) =
20372037
::cast::reinterpret_cast(&addr_of(&pair));
20382038
f(*v)
@@ -2501,6 +2501,18 @@ mod tests {
25012501
assert (!is_not_empty::<int>(~[]));
25022502
}
25032503

2504+
#[test]
2505+
fn test_len_divzero() {
2506+
type Z = [i8 * 0];
2507+
let v0 : &[Z] = &[];
2508+
let v1 : &[Z] = &[[]];
2509+
let v2 : &[Z] = &[[], []];
2510+
assert(sys::size_of::<Z>() == 0);
2511+
assert(len(v0) == 0);
2512+
assert(len(v1) == 1);
2513+
assert(len(v2) == 2);
2514+
}
2515+
25042516
#[test]
25052517
fn test_head() {
25062518
let a = ~[11, 12];

src/librustc/middle/trans/machine.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,17 @@ pub fn llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
132132
}
133133
}
134134

135+
// Returns the "default" size of t (see above), or 1 if the size would
136+
// be zero. This is important for things like vectors that expect
137+
// space to be consumed.
138+
pub fn nonzero_llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
139+
if llbitsize_of_real(cx, t) == 0 {
140+
unsafe { llvm::LLVMConstInt(cx.int_type, 1, False) }
141+
} else {
142+
llsize_of(cx, t)
143+
}
144+
}
145+
135146
// Returns the preferred alignment of the given type for the current target.
136147
// The preffered alignment may be larger than the alignment used when
137148
// packing the type into structs. This will be used for things like

src/librustc/middle/trans/tvec.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use middle::trans::datum::*;
1717
use middle::trans::expr::{Dest, Ignore, SaveIn};
1818
use middle::trans::expr;
1919
use middle::trans::glue;
20-
use middle::trans::shape::llsize_of;
20+
use middle::trans::shape::{llsize_of, nonzero_llsize_of};
2121
use middle::trans::type_of;
2222
use middle::ty;
2323
use util::common::indenter;
@@ -96,7 +96,7 @@ fn alloc_vec(bcx: block, unit_ty: ty::t, elts: uint, heap: heap) -> Result {
9696
let _icx = bcx.insn_ctxt("tvec::alloc_uniq");
9797
let ccx = bcx.ccx();
9898
let llunitty = type_of::type_of(ccx, unit_ty);
99-
let unit_sz = llsize_of(ccx, llunitty);
99+
let unit_sz = nonzero_llsize_of(ccx, llunitty);
100100

101101
let fill = Mul(bcx, C_uint(ccx, elts), unit_sz);
102102
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 {
418418
let ccx = bcx.ccx();
419419
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
420420
let llunit_ty = type_of::type_of(ccx, unit_ty);
421-
let llunit_size = llsize_of(ccx, llunit_ty);
421+
let llunit_size = nonzero_llsize_of(ccx, llunit_ty);
422+
422423
VecTypes {vec_ty: vec_ty,
423424
unit_ty: unit_ty,
424425
llunit_ty: llunit_ty,

0 commit comments

Comments
 (0)