1 // Copyright 2012-2014 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.
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.
11 //! Basic functions for dealing with memory
13 //! This module contains functions for querying the size and alignment of
14 //! types, initializing and manipulating memory.
16 #![allow(missing_doc)] // FIXME
21 use intrinsics::{bswap16, bswap32, bswap64};
23 /// Returns the size of a type in bytes.
25 pub fn size_of<T>() -> uint {
26 unsafe { intrinsics::size_of::<T>() }
29 /// Returns the size of the type that `_val` points to in bytes.
31 pub fn size_of_val<T>(_val: &T) -> uint {
35 /// Returns the size of a type in bytes, or 1 if the actual size is zero.
37 /// Useful for building structures containing variable-length arrays.
39 pub fn nonzero_size_of<T>() -> uint {
40 let s = size_of::<T>();
41 if s == 0 { 1 } else { s }
44 /// Returns the size in bytes of the type of the value that `_val` points to.
46 pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
47 nonzero_size_of::<T>()
50 /// Returns the ABI-required minimum alignment of a type
52 /// This is the alignment used for struct fields. It may be smaller
53 /// than the preferred alignment.
55 pub fn min_align_of<T>() -> uint {
56 unsafe { intrinsics::min_align_of::<T>() }
59 /// Returns the ABI-required minimum alignment of the type of the value that
62 pub fn min_align_of_val<T>(_val: &T) -> uint {
66 /// Returns the preferred alignment of a type
68 pub fn pref_align_of<T>() -> uint {
69 unsafe { intrinsics::pref_align_of::<T>() }
72 /// Returns the preferred alignment of the type of the value that
75 pub fn pref_align_of_val<T>(_val: &T) -> uint {
79 /// Create a value initialized to zero.
81 /// `init` is unsafe because it returns a zeroed-out datum,
82 /// which is unsafe unless T is Copy.
84 pub unsafe fn init<T>() -> T {
88 /// Create an uninitialized value.
90 pub unsafe fn uninit<T>() -> T {
94 /// Move a value to an uninitialized memory location.
96 /// Drop glue is not run on the destination.
98 pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
99 intrinsics::move_val_init(dst, src)
102 /// Convert an u16 to little endian from the target's endianness.
104 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
105 #[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: u16) -> u16 { x }
107 /// Convert an u16 to little endian from the target's endianness.
109 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
110 #[cfg(target_endian = "big")] #[inline] pub fn to_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
112 /// Convert an u32 to little endian from the target's endianness.
114 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
115 #[cfg(target_endian = "little")] #[inline] pub fn to_le32(x: u32) -> u32 { x }
117 /// Convert an u32 to little endian from the target's endianness.
119 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
120 #[cfg(target_endian = "big")] #[inline] pub fn to_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
122 /// Convert an u64 to little endian from the target's endianness.
124 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
125 #[cfg(target_endian = "little")] #[inline] pub fn to_le64(x: u64) -> u64 { x }
127 /// Convert an u64 to little endian from the target's endianness.
129 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
130 #[cfg(target_endian = "big")] #[inline] pub fn to_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
133 /// Convert an u16 to big endian from the target's endianness.
135 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
136 #[cfg(target_endian = "little")] #[inline] pub fn to_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
138 /// Convert an u16 to big endian from the target's endianness.
140 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
141 #[cfg(target_endian = "big")] #[inline] pub fn to_be16(x: u16) -> u16 { x }
143 /// Convert an u32 to big endian from the target's endianness.
145 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
146 #[cfg(target_endian = "little")] #[inline] pub fn to_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
148 /// Convert an u32 to big endian from the target's endianness.
150 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
151 #[cfg(target_endian = "big")] #[inline] pub fn to_be32(x: u32) -> u32 { x }
153 /// Convert an u64 to big endian from the target's endianness.
155 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
156 #[cfg(target_endian = "little")] #[inline] pub fn to_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
158 /// Convert an u64 to big endian from the target's endianness.
160 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
161 #[cfg(target_endian = "big")] #[inline] pub fn to_be64(x: u64) -> u64 { x }
164 /// Convert an u16 from little endian to the target's endianness.
166 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
167 #[cfg(target_endian = "little")] #[inline] pub fn from_le16(x: u16) -> u16 { x }
169 /// Convert an u16 from little endian to the target's endianness.
171 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
172 #[cfg(target_endian = "big")] #[inline] pub fn from_le16(x: u16) -> u16 { unsafe { bswap16(x) } }
174 /// Convert an u32 from little endian to the target's endianness.
176 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
177 #[cfg(target_endian = "little")] #[inline] pub fn from_le32(x: u32) -> u32 { x }
179 /// Convert an u32 from little endian to the target's endianness.
181 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
182 #[cfg(target_endian = "big")] #[inline] pub fn from_le32(x: u32) -> u32 { unsafe { bswap32(x) } }
184 /// Convert an u64 from little endian to the target's endianness.
186 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
187 #[cfg(target_endian = "little")] #[inline] pub fn from_le64(x: u64) -> u64 { x }
189 /// Convert an u64 from little endian to the target's endianness.
191 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
192 #[cfg(target_endian = "big")] #[inline] pub fn from_le64(x: u64) -> u64 { unsafe { bswap64(x) } }
195 /// Convert an u16 from big endian to the target's endianness.
197 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
198 #[cfg(target_endian = "little")] #[inline] pub fn from_be16(x: u16) -> u16 { unsafe { bswap16(x) } }
200 /// Convert an u16 from big endian to the target's endianness.
202 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
203 #[cfg(target_endian = "big")] #[inline] pub fn from_be16(x: u16) -> u16 { x }
205 /// Convert an u32 from big endian to the target's endianness.
207 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
208 #[cfg(target_endian = "little")] #[inline] pub fn from_be32(x: u32) -> u32 { unsafe { bswap32(x) } }
210 /// Convert an u32 from big endian to the target's endianness.
212 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
213 #[cfg(target_endian = "big")] #[inline] pub fn from_be32(x: u32) -> u32 { x }
215 /// Convert an u64 from big endian to the target's endianness.
217 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
218 #[cfg(target_endian = "little")] #[inline] pub fn from_be64(x: u64) -> u64 { unsafe { bswap64(x) } }
220 /// Convert an u64 from big endian to the target's endianness.
222 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
223 #[cfg(target_endian = "big")] #[inline] pub fn from_be64(x: u64) -> u64 { x }
227 * Swap the values at two mutable locations of the same type, without
228 * deinitialising or copying either one.
231 pub fn swap<T>(x: &mut T, y: &mut T) {
233 // Give ourselves some scratch space to work with
234 let mut t: T = uninit();
236 // Perform the swap, `&mut` pointers never alias
237 ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
238 ptr::copy_nonoverlapping_memory(x, &*y, 1);
239 ptr::copy_nonoverlapping_memory(y, &t, 1);
241 // y and t now point to the same thing, but we need to completely forget `tmp`
242 // because it's no longer relevant.
248 * Replace the value at a mutable location with a new one, returning the old
249 * value, without deinitialising or copying either one.
252 pub fn replace<T>(dest: &mut T, mut src: T) -> T {
253 swap(dest, &mut src);
257 /// Disposes of a value.
259 pub fn drop<T>(_x: T) { }
264 use option::{Some,None};
268 assert_eq!(size_of::<u8>(), 1u);
269 assert_eq!(size_of::<u16>(), 2u);
270 assert_eq!(size_of::<u32>(), 4u);
271 assert_eq!(size_of::<u64>(), 8u);
275 #[cfg(target_arch = "x86")]
276 #[cfg(target_arch = "arm")]
277 #[cfg(target_arch = "mips")]
279 assert_eq!(size_of::<uint>(), 4u);
280 assert_eq!(size_of::<*uint>(), 4u);
284 #[cfg(target_arch = "x86_64")]
286 assert_eq!(size_of::<uint>(), 8u);
287 assert_eq!(size_of::<*uint>(), 8u);
291 fn size_of_val_basic() {
292 assert_eq!(size_of_val(&1u8), 1);
293 assert_eq!(size_of_val(&1u16), 2);
294 assert_eq!(size_of_val(&1u32), 4);
295 assert_eq!(size_of_val(&1u64), 8);
299 fn nonzero_size_of_basic() {
301 assert_eq!(size_of::<Z>(), 0u);
302 assert_eq!(nonzero_size_of::<Z>(), 1u);
303 assert_eq!(nonzero_size_of::<uint>(), size_of::<uint>());
307 fn nonzero_size_of_val_basic() {
309 assert_eq!(size_of_val(&z), 0u);
310 assert_eq!(nonzero_size_of_val(&z), 1u);
311 assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
315 fn align_of_basic() {
316 assert_eq!(pref_align_of::<u8>(), 1u);
317 assert_eq!(pref_align_of::<u16>(), 2u);
318 assert_eq!(pref_align_of::<u32>(), 4u);
322 #[cfg(target_arch = "x86")]
323 #[cfg(target_arch = "arm")]
324 #[cfg(target_arch = "mips")]
326 assert_eq!(pref_align_of::<uint>(), 4u);
327 assert_eq!(pref_align_of::<*uint>(), 4u);
331 #[cfg(target_arch = "x86_64")]
333 assert_eq!(pref_align_of::<uint>(), 8u);
334 assert_eq!(pref_align_of::<*uint>(), 8u);
338 fn align_of_val_basic() {
339 assert_eq!(pref_align_of_val(&1u8), 1u);
340 assert_eq!(pref_align_of_val(&1u16), 2u);
341 assert_eq!(pref_align_of_val(&1u32), 4u);
348 swap(&mut x, &mut y);
350 assert_eq!(y, 31337);
355 let mut x = Some(~"test");
356 let y = replace(&mut x, None);
357 assert!(x.is_none());
358 assert!(y.is_some());
362 /// Completely miscellaneous language-construct benchmarks.
366 use self::test::Bencher;
367 use option::{Some,None};
369 // Static/dynamic method dispatch
376 fn method(&self) -> int;
379 impl Trait for Struct {
380 fn method(&self) -> int {
386 fn trait_vtable_method_call(b: &mut Bencher) {
387 let s = Struct { field: 10 };
388 let t = &s as &Trait;
395 fn trait_static_method_call(b: &mut Bencher) {
396 let s = Struct { field: 10 };
402 // Overhead of various match forms
405 fn match_option_some(b: &mut Bencher) {
416 fn match_vec_pattern(b: &mut Bencher) {
417 let x = [1,2,3,4,5,6];