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.
19 use intrinsics::{bswap16, bswap32, bswap64};
21 pub use intrinsics::transmute;
23 /// Returns the size of a type in bytes.
26 pub fn size_of<T>() -> uint {
27 unsafe { intrinsics::size_of::<T>() }
30 /// Returns the size of the type that `_val` points to in bytes.
33 pub fn size_of_val<T>(_val: &T) -> uint {
37 /// Deprecated, this function will be removed soon
39 #[deprecated = "this function will be removed soon"]
40 pub fn nonzero_size_of<T>() -> uint {
41 match size_of::<T>() {
47 /// Deprecated, this function will be removed soon
49 #[deprecated = "this function will be removed soon"]
50 pub fn nonzero_size_of_val<T>(val: &T) -> uint {
51 match size_of_val::<T>(val) {
57 /// Returns the ABI-required minimum alignment of a type
59 /// This is the alignment used for struct fields. It may be smaller
60 /// than the preferred alignment.
63 pub fn min_align_of<T>() -> uint {
64 unsafe { intrinsics::min_align_of::<T>() }
67 /// Returns the ABI-required minimum alignment of the type of the value that
71 pub fn min_align_of_val<T>(_val: &T) -> uint {
75 /// Returns the alignment in memory for a type.
77 /// This function will return the alignment, in bytes, of a type in memory. If
78 /// the alignment returned is adhered to, then the type is guaranteed to
79 /// function properly.
82 pub fn align_of<T>() -> uint {
83 // We use the preferred alignment as the default alignment for a type. This
84 // appears to be what clang migrated towards as well:
86 // http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20110725/044411.html
87 unsafe { intrinsics::pref_align_of::<T>() }
90 /// Returns the alignment of the type of the value that `_val` points to.
92 /// This is similar to `align_of`, but function will properly handle types such
93 /// as trait objects (in the future), returning the alignment for an arbitrary
97 pub fn align_of_val<T>(_val: &T) -> uint {
101 /// Deprecated, this function has been renamed to align_of
103 #[deprecated = "use mem::align_of instead"]
104 pub fn pref_align_of<T>() -> uint { align_of::<T>() }
106 /// Deprecated, this function has been renamed to align_of_val
108 #[deprecated = "use mem::align_of_val instead"]
109 pub fn pref_align_of_val<T>(val: &T) -> uint { align_of_val(val) }
111 /// Create a value initialized to zero.
113 /// This function is similar to allocating space for a a local variable and
114 /// zeroing it out (an unsafe operation).
116 /// Care must be taken when using this function, if the type `T` has a
117 /// destructor and the value falls out of scope (due to unwinding or returning)
118 /// before being initialized, then the destructor will run on zeroed
119 /// data, likely leading to crashes.
121 /// This is useful for FFI functions sometimes, but should generally be avoided.
124 pub unsafe fn zeroed<T>() -> T {
128 /// Deprecated, use zeroed() instead
130 #[deprecated = "this function has been renamed to zeroed()"]
131 pub unsafe fn init<T>() -> T { zeroed() }
133 /// Create an uninitialized value.
135 /// Care must be taken when using this function, if the type `T` has a
136 /// destructor and the value falls out of scope (due to unwinding or returning)
137 /// before being initialized, then the destructor will run on uninitialized
138 /// data, likely leading to crashes.
140 /// This is useful for FFI functions sometimes, but should generally be avoided.
143 pub unsafe fn uninitialized<T>() -> T {
147 /// Deprecated, use `uninitialized` instead.
149 #[deprecated = "this function has been renamed to `uninitialized`"]
150 pub unsafe fn uninit<T>() -> T {
154 /// Unsafely overwrite a memory location with the given value without destroying
157 /// This operation is unsafe because it does not destroy the previous value
158 /// contained at the location `dst`. This could leak allocations or resources,
159 /// so care must be taken to previously deallocate the value at `dst`.
161 #[deprecated = "use ptr::write"]
162 pub unsafe fn overwrite<T>(dst: *mut T, src: T) {
163 intrinsics::move_val_init(&mut *dst, src)
166 /// Deprecated, use `overwrite` instead
168 #[deprecated = "use ptr::write"]
169 pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
173 /// A type that can have its bytes re-ordered.
174 pub trait ByteOrder: Clone {
175 /// Reverses the byte order of the value.
180 /// use std::mem::ByteOrder;
182 /// let n = 0x0123456789ABCDEFu64;
183 /// let m = 0xEFCDAB8967452301u64;
185 /// assert_eq!(n.swap_bytes(), m);
187 fn swap_bytes(&self) -> Self;
189 /// Convert a value from big endian to the target's endianness.
191 /// On big endian this is a no-op. On little endian the bytes are swapped.
196 /// use std::mem::ByteOrder;
198 /// let n = 0x0123456789ABCDEFu64;
200 /// if cfg!(target_endian = "big") {
201 /// assert_eq!(ByteOrder::from_big_endian(n), n)
203 /// assert_eq!(ByteOrder::from_big_endian(n), n.swap_bytes())
207 fn from_big_endian(x: Self) -> Self {
208 if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
211 /// Convert a value from little endian to the target's endianness.
213 /// On little endian this is a no-op. On big endian the bytes are swapped.
218 /// use std::mem::ByteOrder;
220 /// let n = 0x0123456789ABCDEFu64;
222 /// if cfg!(target_endian = "little") {
223 /// assert_eq!(ByteOrder::from_little_endian(n), n)
225 /// assert_eq!(ByteOrder::from_little_endian(n), n.swap_bytes())
229 fn from_little_endian(x: Self) -> Self {
230 if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
233 /// Convert the value to big endian from the target's endianness.
235 /// On big endian this is a no-op. On little endian the bytes are swapped.
240 /// use std::mem::ByteOrder;
242 /// let n = 0x0123456789ABCDEFu64;
244 /// if cfg!(target_endian = "big") {
245 /// assert_eq!(n.to_big_endian(), n)
247 /// assert_eq!(n.to_big_endian(), n.swap_bytes())
251 fn to_big_endian(&self) -> Self {
252 if cfg!(target_endian = "big") { self.clone() } else { self.swap_bytes() }
255 /// Convert the value to little endian from the target's endianness.
257 /// On little endian this is a no-op. On big endian the bytes are swapped.
262 /// use std::mem::ByteOrder;
264 /// let n = 0x0123456789ABCDEFu64;
266 /// if cfg!(target_endian = "little") {
267 /// assert_eq!(n.to_little_endian(), n)
269 /// assert_eq!(n.to_little_endian(), n.swap_bytes())
273 fn to_little_endian(&self) -> Self {
274 if cfg!(target_endian = "little") { self.clone() } else { self.swap_bytes() }
278 impl ByteOrder for u8 {
280 fn swap_bytes(&self) -> u8 {
281 *self // swapping a single byte does nothing
285 impl ByteOrder for u16 {
287 fn swap_bytes(&self) -> u16 {
288 unsafe { intrinsics::bswap16(*self) }
292 impl ByteOrder for u32 {
294 fn swap_bytes(&self) -> u32 {
295 unsafe { intrinsics::bswap32(*self) }
299 impl ByteOrder for u64 {
301 fn swap_bytes(&self) -> u64 {
302 unsafe { intrinsics::bswap64(*self) }
306 #[cfg(target_word_size = "32")]
307 impl ByteOrder for uint {
309 fn swap_bytes(&self) -> uint {
310 (*self as u32).swap_bytes() as uint
314 #[cfg(target_word_size = "64")]
315 impl ByteOrder for uint {
317 fn swap_bytes(&self) -> uint {
318 (*self as u64).swap_bytes() as uint
322 /// Convert an u16 to little endian from the target's endianness.
324 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
327 pub fn to_le16(x: u16) -> u16 { x.to_little_endian() }
329 /// Convert an u32 to little endian from the target's endianness.
331 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
334 pub fn to_le32(x: u32) -> u32 { x.to_little_endian() }
336 /// Convert an u64 to little endian from the target's endianness.
338 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
341 pub fn to_le64(x: u64) -> u64 { x.to_little_endian() }
343 /// Convert an u16 to big endian from the target's endianness.
345 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
348 pub fn to_be16(x: u16) -> u16 { x.to_big_endian() }
350 /// Convert an u32 to big endian from the target's endianness.
352 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
355 pub fn to_be32(x: u32) -> u32 { x.to_big_endian() }
357 /// Convert an u64 to big endian from the target's endianness.
359 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
362 pub fn to_be64(x: u64) -> u64 { x.to_big_endian() }
364 /// Convert an u16 from little endian to the target's endianness.
366 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
369 pub fn from_le16(x: u16) -> u16 { ByteOrder::from_little_endian(x) }
371 /// Convert an u32 from little endian to the target's endianness.
373 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
376 pub fn from_le32(x: u32) -> u32 { ByteOrder::from_little_endian(x) }
378 /// Convert an u64 from little endian to the target's endianness.
380 /// On little endian, this is a no-op. On big endian, the bytes are swapped.
383 pub fn from_le64(x: u64) -> u64 { ByteOrder::from_little_endian(x) }
385 /// Convert an u16 from big endian to the target's endianness.
387 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
390 pub fn from_be16(x: u16) -> u16 { ByteOrder::from_big_endian(x) }
392 /// Convert an u32 from big endian to the target's endianness.
394 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
397 pub fn from_be32(x: u32) -> u32 { ByteOrder::from_big_endian(x) }
399 /// Convert an u64 from big endian to the target's endianness.
401 /// On big endian, this is a no-op. On little endian, the bytes are swapped.
404 pub fn from_be64(x: u64) -> u64 { ByteOrder::from_big_endian(x) }
407 * Swap the values at two mutable locations of the same type, without
408 * deinitialising or copying either one.
412 pub fn swap<T>(x: &mut T, y: &mut T) {
414 // Give ourselves some scratch space to work with
415 let mut t: T = uninitialized();
417 // Perform the swap, `&mut` pointers never alias
418 ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
419 ptr::copy_nonoverlapping_memory(x, &*y, 1);
420 ptr::copy_nonoverlapping_memory(y, &t, 1);
422 // y and t now point to the same thing, but we need to completely forget `t`
423 // because it's no longer relevant.
429 * Replace the value at a mutable location with a new one, returning the old
430 * value, without deinitialising or copying either one.
432 * This is primarily used for transferring and swapping ownership of a value
433 * in a mutable location. For example, this function allows consumption of
434 * one field of a struct by replacing it with another value. The normal approach
435 * doesn't always work:
438 * struct Buffer<T> { buf: Vec<T> }
440 * impl<T> Buffer<T> {
441 * fn get_and_reset(&mut self) -> Vec<T> {
442 * // error: cannot move out of dereference of `&mut`-pointer
443 * let buf = self.buf;
444 * self.buf = Vec::new();
450 * Note that `T` does not necessarily implement `Clone`, so it can't even
451 * clone and reset `self.buf`. But `replace` can be used to disassociate
452 * the original value of `self.buf` from `self`, allowing it to be returned:
455 * # struct Buffer<T> { buf: Vec<T> }
456 * impl<T> Buffer<T> {
457 * fn get_and_reset(&mut self) -> Vec<T> {
458 * use std::mem::replace;
459 * replace(&mut self.buf, Vec::new())
466 pub fn replace<T>(dest: &mut T, mut src: T) -> T {
467 swap(dest, &mut src);
471 /// Disposes of a value.
473 /// This function can be used to destroy any value by allowing `drop` to take
474 /// ownership of its argument.
479 /// use std::cell::RefCell;
481 /// let x = RefCell::new(1);
483 /// let mut mutable_borrow = x.borrow_mut();
484 /// *mutable_borrow = 1;
485 /// drop(mutable_borrow); // relinquish the mutable borrow on this slot
487 /// let borrow = x.borrow();
488 /// println!("{}", *borrow);
492 pub fn drop<T>(_x: T) { }
494 /// Moves a thing into the void.
496 /// The forget function will take ownership of the provided value but neglect
497 /// to run any required cleanup or memory management operations on it.
499 /// This function is the unsafe version of the `drop` function because it does
500 /// not run any destructors.
503 pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing) }
505 /// Interprets `src` as `&U`, and then reads `src` without moving the contained
508 /// This function will unsafely assume the pointer `src` is valid for
509 /// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It
510 /// will also unsafely create a copy of the contained value instead of moving
513 /// It is not a compile-time error if `T` and `U` have different sizes, but it
514 /// is highly encouraged to only invoke this function where `T` and `U` have the
515 /// same size. This function triggers undefined behavior if `U` is larger than
519 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
520 ptr::read(src as *T as *U)
523 /// Transforms lifetime of the second pointer to match the first.
525 #[unstable = "this function may be removed in the future due to its \
526 questionable utility"]
527 pub unsafe fn copy_lifetime<'a, S, T>(_ptr: &'a S, ptr: &T) -> &'a T {
531 /// Transforms lifetime of the second mutable pointer to match the first.
533 #[unstable = "this function may be removed in the future due to its \
534 questionable utility"]
535 pub unsafe fn copy_mut_lifetime<'a, S, T>(_ptr: &'a mut S,
536 ptr: &mut T) -> &'a mut T {
543 use option::{Some,None};
544 use realstd::str::StrAllocating;
545 use realstd::owned::Box;
546 use realstd::vec::Vec;
551 assert_eq!(size_of::<u8>(), 1u);
552 assert_eq!(size_of::<u16>(), 2u);
553 assert_eq!(size_of::<u32>(), 4u);
554 assert_eq!(size_of::<u64>(), 8u);
558 #[cfg(target_arch = "x86")]
559 #[cfg(target_arch = "arm")]
560 #[cfg(target_arch = "mips")]
562 assert_eq!(size_of::<uint>(), 4u);
563 assert_eq!(size_of::<*uint>(), 4u);
567 #[cfg(target_arch = "x86_64")]
569 assert_eq!(size_of::<uint>(), 8u);
570 assert_eq!(size_of::<*uint>(), 8u);
574 fn size_of_val_basic() {
575 assert_eq!(size_of_val(&1u8), 1);
576 assert_eq!(size_of_val(&1u16), 2);
577 assert_eq!(size_of_val(&1u32), 4);
578 assert_eq!(size_of_val(&1u64), 8);
582 fn align_of_basic() {
583 assert_eq!(align_of::<u8>(), 1u);
584 assert_eq!(align_of::<u16>(), 2u);
585 assert_eq!(align_of::<u32>(), 4u);
589 #[cfg(target_arch = "x86")]
590 #[cfg(target_arch = "arm")]
591 #[cfg(target_arch = "mips")]
593 assert_eq!(align_of::<uint>(), 4u);
594 assert_eq!(align_of::<*uint>(), 4u);
598 #[cfg(target_arch = "x86_64")]
600 assert_eq!(align_of::<uint>(), 8u);
601 assert_eq!(align_of::<*uint>(), 8u);
605 fn align_of_val_basic() {
606 assert_eq!(align_of_val(&1u8), 1u);
607 assert_eq!(align_of_val(&1u16), 2u);
608 assert_eq!(align_of_val(&1u32), 4u);
615 swap(&mut x, &mut y);
617 assert_eq!(y, 31337);
622 let mut x = Some("test".to_string());
623 let y = replace(&mut x, None);
624 assert!(x.is_none());
625 assert!(y.is_some());
629 fn test_transmute_copy() {
630 assert_eq!(1u, unsafe { ::mem::transmute_copy(&1) });
634 fn test_transmute() {
638 let a = box 100 as Box<Foo>;
640 let x: raw::TraitObject = transmute(a);
641 assert!(*(x.data as *int) == 100);
642 let _x: Box<Foo> = transmute(x);
646 assert!(Vec::from_slice([76u8]) == transmute("L".to_string()));
650 macro_rules! test_byte_order {
655 static A: $T = 0b0101100;
656 static B: $T = 0b0100001;
657 static C: $T = 0b1111001;
663 fn test_swap_bytes() {
664 assert_eq!(A.swap_bytes().swap_bytes(), A);
665 assert_eq!(B.swap_bytes().swap_bytes(), B);
666 assert_eq!(C.swap_bytes().swap_bytes(), C);
668 // Swapping these should make no difference
669 assert_eq!(_0.swap_bytes(), _0);
670 assert_eq!(_1.swap_bytes(), _1);
674 fn test_little_endian() {
675 assert_eq!(ByteOrder::from_little_endian(A.to_little_endian()), A);
676 assert_eq!(ByteOrder::from_little_endian(B.to_little_endian()), B);
677 assert_eq!(ByteOrder::from_little_endian(C.to_little_endian()), C);
678 assert_eq!(ByteOrder::from_little_endian(_0), _0);
679 assert_eq!(ByteOrder::from_little_endian(_1), _1);
680 assert_eq!(_0.to_little_endian(), _0);
681 assert_eq!(_1.to_little_endian(), _1);
685 fn test_big_endian() {
686 assert_eq!(ByteOrder::from_big_endian(A.to_big_endian()), A);
687 assert_eq!(ByteOrder::from_big_endian(B.to_big_endian()), B);
688 assert_eq!(ByteOrder::from_big_endian(C.to_big_endian()), C);
689 assert_eq!(ByteOrder::from_big_endian(_0), _0);
690 assert_eq!(ByteOrder::from_big_endian(_1), _1);
691 assert_eq!(_0.to_big_endian(), _0);
692 assert_eq!(_1.to_big_endian(), _1);
699 test_byte_order!(u16)
700 test_byte_order!(u32)
701 test_byte_order!(u64)
702 test_byte_order!(uint)
705 // FIXME #13642 (these benchmarks should be in another place)
706 /// Completely miscellaneous language-construct benchmarks.
710 use self::test::Bencher;
711 use option::{Some,None};
713 // Static/dynamic method dispatch
720 fn method(&self) -> int;
723 impl Trait for Struct {
724 fn method(&self) -> int {
730 fn trait_vtable_method_call(b: &mut Bencher) {
731 let s = Struct { field: 10 };
732 let t = &s as &Trait;
739 fn trait_static_method_call(b: &mut Bencher) {
740 let s = Struct { field: 10 };
746 // Overhead of various match forms
749 fn match_option_some(b: &mut Bencher) {
760 fn match_vec_pattern(b: &mut Bencher) {
761 let x = [1,2,3,4,5,6];