Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 26bd433

Browse files
committedFeb 13, 2019
Move the intrinsics into a submodule
1 parent ccd23b9 commit 26bd433

File tree

1 file changed

+249
-215
lines changed

1 file changed

+249
-215
lines changed
 

‎src/libcore/intrinsics.rs

Lines changed: 249 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -962,221 +962,6 @@ extern "rust-intrinsic" {
962962
/// value is not necessarily valid to be used to actually access memory.
963963
pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
964964

965-
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
966-
/// and destination must *not* overlap.
967-
///
968-
/// For regions of memory which might overlap, use [`copy`] instead.
969-
///
970-
/// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
971-
/// with the argument order swapped.
972-
///
973-
/// [`copy`]: ./fn.copy.html
974-
/// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy
975-
///
976-
/// # Safety
977-
///
978-
/// Behavior is undefined if any of the following conditions are violated:
979-
///
980-
/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
981-
///
982-
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
983-
///
984-
/// * Both `src` and `dst` must be properly aligned.
985-
///
986-
/// * The region of memory beginning at `src` with a size of `count *
987-
/// size_of::<T>()` bytes must *not* overlap with the region of memory
988-
/// beginning at `dst` with the same size.
989-
///
990-
/// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
991-
/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values
992-
/// in the region beginning at `*src` and the region beginning at `*dst` can
993-
/// [violate memory safety][read-ownership].
994-
///
995-
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
996-
/// `0`, the pointers must be non-NULL and properly aligned.
997-
///
998-
/// [`Copy`]: ../marker/trait.Copy.html
999-
/// [`read`]: ../ptr/fn.read.html
1000-
/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
1001-
/// [valid]: ../ptr/index.html#safety
1002-
///
1003-
/// # Examples
1004-
///
1005-
/// Manually implement [`Vec::append`]:
1006-
///
1007-
/// ```
1008-
/// use std::ptr;
1009-
///
1010-
/// /// Moves all the elements of `src` into `dst`, leaving `src` empty.
1011-
/// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) {
1012-
/// let src_len = src.len();
1013-
/// let dst_len = dst.len();
1014-
///
1015-
/// // Ensure that `dst` has enough capacity to hold all of `src`.
1016-
/// dst.reserve(src_len);
1017-
///
1018-
/// unsafe {
1019-
/// // The call to offset is always safe because `Vec` will never
1020-
/// // allocate more than `isize::MAX` bytes.
1021-
/// let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize);
1022-
/// let src_ptr = src.as_ptr();
1023-
///
1024-
/// // Truncate `src` without dropping its contents. We do this first,
1025-
/// // to avoid problems in case something further down panics.
1026-
/// src.set_len(0);
1027-
///
1028-
/// // The two regions cannot overlap because mutable references do
1029-
/// // not alias, and two different vectors cannot own the same
1030-
/// // memory.
1031-
/// ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);
1032-
///
1033-
/// // Notify `dst` that it now holds the contents of `src`.
1034-
/// dst.set_len(dst_len + src_len);
1035-
/// }
1036-
/// }
1037-
///
1038-
/// let mut a = vec!['r'];
1039-
/// let mut b = vec!['u', 's', 't'];
1040-
///
1041-
/// append(&mut a, &mut b);
1042-
///
1043-
/// assert_eq!(a, &['r', 'u', 's', 't']);
1044-
/// assert!(b.is_empty());
1045-
/// ```
1046-
///
1047-
/// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append
1048-
#[stable(feature = "rust1", since = "1.0.0")]
1049-
pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
1050-
1051-
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
1052-
/// and destination may overlap.
1053-
///
1054-
/// If the source and destination will *never* overlap,
1055-
/// [`copy_nonoverlapping`] can be used instead.
1056-
///
1057-
/// `copy` is semantically equivalent to C's [`memmove`], but with the argument
1058-
/// order swapped. Copying takes place as if the bytes were copied from `src`
1059-
/// to a temporary array and then copied from the array to `dst`.
1060-
///
1061-
/// [`copy_nonoverlapping`]: ./fn.copy_nonoverlapping.html
1062-
/// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove
1063-
///
1064-
/// # Safety
1065-
///
1066-
/// Behavior is undefined if any of the following conditions are violated:
1067-
///
1068-
/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
1069-
///
1070-
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
1071-
///
1072-
/// * Both `src` and `dst` must be properly aligned.
1073-
///
1074-
/// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of
1075-
/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values
1076-
/// in the region beginning at `*src` and the region beginning at `*dst` can
1077-
/// [violate memory safety][read-ownership].
1078-
///
1079-
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
1080-
/// `0`, the pointers must be non-NULL and properly aligned.
1081-
///
1082-
/// [`Copy`]: ../marker/trait.Copy.html
1083-
/// [`read`]: ../ptr/fn.read.html
1084-
/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
1085-
/// [valid]: ../ptr/index.html#safety
1086-
///
1087-
/// # Examples
1088-
///
1089-
/// Efficiently create a Rust vector from an unsafe buffer:
1090-
///
1091-
/// ```
1092-
/// use std::ptr;
1093-
///
1094-
/// # #[allow(dead_code)]
1095-
/// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
1096-
/// let mut dst = Vec::with_capacity(elts);
1097-
/// dst.set_len(elts);
1098-
/// ptr::copy(ptr, dst.as_mut_ptr(), elts);
1099-
/// dst
1100-
/// }
1101-
/// ```
1102-
#[stable(feature = "rust1", since = "1.0.0")]
1103-
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
1104-
1105-
/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
1106-
/// `val`.
1107-
///
1108-
/// `write_bytes` is similar to C's [`memset`], but sets `count *
1109-
/// size_of::<T>()` bytes to `val`.
1110-
///
1111-
/// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset
1112-
///
1113-
/// # Safety
1114-
///
1115-
/// Behavior is undefined if any of the following conditions are violated:
1116-
///
1117-
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
1118-
///
1119-
/// * `dst` must be properly aligned.
1120-
///
1121-
/// Additionally, the caller must ensure that writing `count *
1122-
/// size_of::<T>()` bytes to the given region of memory results in a valid
1123-
/// value of `T`. Using a region of memory typed as a `T` that contains an
1124-
/// invalid value of `T` is undefined behavior.
1125-
///
1126-
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
1127-
/// `0`, the pointer must be non-NULL and properly aligned.
1128-
///
1129-
/// [valid]: ../ptr/index.html#safety
1130-
///
1131-
/// # Examples
1132-
///
1133-
/// Basic usage:
1134-
///
1135-
/// ```
1136-
/// use std::ptr;
1137-
///
1138-
/// let mut vec = vec![0u32; 4];
1139-
/// unsafe {
1140-
/// let vec_ptr = vec.as_mut_ptr();
1141-
/// ptr::write_bytes(vec_ptr, 0xfe, 2);
1142-
/// }
1143-
/// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]);
1144-
/// ```
1145-
///
1146-
/// Creating an invalid value:
1147-
///
1148-
/// ```
1149-
/// use std::ptr;
1150-
///
1151-
/// let mut v = Box::new(0i32);
1152-
///
1153-
/// unsafe {
1154-
/// // Leaks the previously held value by overwriting the `Box<T>` with
1155-
/// // a null pointer.
1156-
/// ptr::write_bytes(&mut v as *mut Box<i32>, 0, 1);
1157-
/// }
1158-
///
1159-
/// // At this point, using or dropping `v` results in undefined behavior.
1160-
/// // drop(v); // ERROR
1161-
///
1162-
/// // Even leaking `v` "uses" it, and hence is undefined behavior.
1163-
/// // mem::forget(v); // ERROR
1164-
///
1165-
/// // In fact, `v` is invalid according to basic type layout invariants, so *any*
1166-
/// // operation touching it is undefined behavior.
1167-
/// // let v2 = v; // ERROR
1168-
///
1169-
/// unsafe {
1170-
/// // Let us instead put in a valid value
1171-
/// ptr::write(&mut v as *mut Box<i32>, Box::new(42i32));
1172-
/// }
1173-
///
1174-
/// // Now the box is fine
1175-
/// assert_eq!(*v, 42);
1176-
/// ```
1177-
#[stable(feature = "rust1", since = "1.0.0")]
1178-
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
1179-
1180965
/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
1181966
/// a size of `count` * `size_of::<T>()` and an alignment of
1182967
/// `min_align_of::<T>()`
@@ -1524,3 +1309,252 @@ extern "rust-intrinsic" {
15241309
/// Probably will never become stable.
15251310
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
15261311
}
1312+
1313+
mod real_intrinsics {
1314+
extern "rust-intrinsic" {
1315+
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
1316+
/// and destination must *not* overlap.
1317+
/// For the full docs, see the stabilized wrapper [`copy_nonoverlapping`].
1318+
///
1319+
/// [`copy_nonoverlapping`]: ../../std/ptr/fn.copy_nonoverlapping.html
1320+
pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
1321+
1322+
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
1323+
/// and destination may overlap.
1324+
/// For the full docs, see the stabilized wrapper [`copy`].
1325+
///
1326+
/// [`copy`]: ../../std/ptr/fn.copy.html
1327+
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
1328+
1329+
/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
1330+
/// `val`.
1331+
/// For the full docs, see the stabilized wrapper [`write_bytes`].
1332+
///
1333+
/// [`write_bytes`]: ../../std/ptr/fn.write_bytes.html
1334+
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
1335+
}
1336+
}
1337+
1338+
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
1339+
/// and destination must *not* overlap.
1340+
///
1341+
/// For regions of memory which might overlap, use [`copy`] instead.
1342+
///
1343+
/// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
1344+
/// with the argument order swapped.
1345+
///
1346+
/// [`copy`]: ./fn.copy.html
1347+
/// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy
1348+
///
1349+
/// # Safety
1350+
///
1351+
/// Behavior is undefined if any of the following conditions are violated:
1352+
///
1353+
/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
1354+
///
1355+
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
1356+
///
1357+
/// * Both `src` and `dst` must be properly aligned.
1358+
///
1359+
/// * The region of memory beginning at `src` with a size of `count *
1360+
/// size_of::<T>()` bytes must *not* overlap with the region of memory
1361+
/// beginning at `dst` with the same size.
1362+
///
1363+
/// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
1364+
/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values
1365+
/// in the region beginning at `*src` and the region beginning at `*dst` can
1366+
/// [violate memory safety][read-ownership].
1367+
///
1368+
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
1369+
/// `0`, the pointers must be non-NULL and properly aligned.
1370+
///
1371+
/// [`Copy`]: ../marker/trait.Copy.html
1372+
/// [`read`]: ../ptr/fn.read.html
1373+
/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
1374+
/// [valid]: ../ptr/index.html#safety
1375+
///
1376+
/// # Examples
1377+
///
1378+
/// Manually implement [`Vec::append`]:
1379+
///
1380+
/// ```
1381+
/// use std::ptr;
1382+
///
1383+
/// /// Moves all the elements of `src` into `dst`, leaving `src` empty.
1384+
/// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) {
1385+
/// let src_len = src.len();
1386+
/// let dst_len = dst.len();
1387+
///
1388+
/// // Ensure that `dst` has enough capacity to hold all of `src`.
1389+
/// dst.reserve(src_len);
1390+
///
1391+
/// unsafe {
1392+
/// // The call to offset is always safe because `Vec` will never
1393+
/// // allocate more than `isize::MAX` bytes.
1394+
/// let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize);
1395+
/// let src_ptr = src.as_ptr();
1396+
///
1397+
/// // Truncate `src` without dropping its contents. We do this first,
1398+
/// // to avoid problems in case something further down panics.
1399+
/// src.set_len(0);
1400+
///
1401+
/// // The two regions cannot overlap because mutable references do
1402+
/// // not alias, and two different vectors cannot own the same
1403+
/// // memory.
1404+
/// ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);
1405+
///
1406+
/// // Notify `dst` that it now holds the contents of `src`.
1407+
/// dst.set_len(dst_len + src_len);
1408+
/// }
1409+
/// }
1410+
///
1411+
/// let mut a = vec!['r'];
1412+
/// let mut b = vec!['u', 's', 't'];
1413+
///
1414+
/// append(&mut a, &mut b);
1415+
///
1416+
/// assert_eq!(a, &['r', 'u', 's', 't']);
1417+
/// assert!(b.is_empty());
1418+
/// ```
1419+
///
1420+
/// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append
1421+
#[stable(feature = "rust1", since = "1.0.0")]
1422+
#[inline]
1423+
pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
1424+
real_intrinsics::copy_nonoverlapping(src, dst, count);
1425+
}
1426+
1427+
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
1428+
/// and destination may overlap.
1429+
///
1430+
/// If the source and destination will *never* overlap,
1431+
/// [`copy_nonoverlapping`] can be used instead.
1432+
///
1433+
/// `copy` is semantically equivalent to C's [`memmove`], but with the argument
1434+
/// order swapped. Copying takes place as if the bytes were copied from `src`
1435+
/// to a temporary array and then copied from the array to `dst`.
1436+
///
1437+
/// [`copy_nonoverlapping`]: ./fn.copy_nonoverlapping.html
1438+
/// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove
1439+
///
1440+
/// # Safety
1441+
///
1442+
/// Behavior is undefined if any of the following conditions are violated:
1443+
///
1444+
/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
1445+
///
1446+
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
1447+
///
1448+
/// * Both `src` and `dst` must be properly aligned.
1449+
///
1450+
/// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of
1451+
/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values
1452+
/// in the region beginning at `*src` and the region beginning at `*dst` can
1453+
/// [violate memory safety][read-ownership].
1454+
///
1455+
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
1456+
/// `0`, the pointers must be non-NULL and properly aligned.
1457+
///
1458+
/// [`Copy`]: ../marker/trait.Copy.html
1459+
/// [`read`]: ../ptr/fn.read.html
1460+
/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
1461+
/// [valid]: ../ptr/index.html#safety
1462+
///
1463+
/// # Examples
1464+
///
1465+
/// Efficiently create a Rust vector from an unsafe buffer:
1466+
///
1467+
/// ```
1468+
/// use std::ptr;
1469+
///
1470+
/// # #[allow(dead_code)]
1471+
/// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
1472+
/// let mut dst = Vec::with_capacity(elts);
1473+
/// dst.set_len(elts);
1474+
/// ptr::copy(ptr, dst.as_mut_ptr(), elts);
1475+
/// dst
1476+
/// }
1477+
/// ```
1478+
#[stable(feature = "rust1", since = "1.0.0")]
1479+
#[inline]
1480+
pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
1481+
real_intrinsics::copy(src, dst, count)
1482+
}
1483+
1484+
/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
1485+
/// `val`.
1486+
///
1487+
/// `write_bytes` is similar to C's [`memset`], but sets `count *
1488+
/// size_of::<T>()` bytes to `val`.
1489+
///
1490+
/// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset
1491+
///
1492+
/// # Safety
1493+
///
1494+
/// Behavior is undefined if any of the following conditions are violated:
1495+
///
1496+
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
1497+
///
1498+
/// * `dst` must be properly aligned.
1499+
///
1500+
/// Additionally, the caller must ensure that writing `count *
1501+
/// size_of::<T>()` bytes to the given region of memory results in a valid
1502+
/// value of `T`. Using a region of memory typed as a `T` that contains an
1503+
/// invalid value of `T` is undefined behavior.
1504+
///
1505+
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
1506+
/// `0`, the pointer must be non-NULL and properly aligned.
1507+
///
1508+
/// [valid]: ../ptr/index.html#safety
1509+
///
1510+
/// # Examples
1511+
///
1512+
/// Basic usage:
1513+
///
1514+
/// ```
1515+
/// use std::ptr;
1516+
///
1517+
/// let mut vec = vec![0u32; 4];
1518+
/// unsafe {
1519+
/// let vec_ptr = vec.as_mut_ptr();
1520+
/// ptr::write_bytes(vec_ptr, 0xfe, 2);
1521+
/// }
1522+
/// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]);
1523+
/// ```
1524+
///
1525+
/// Creating an invalid value:
1526+
///
1527+
/// ```
1528+
/// use std::ptr;
1529+
///
1530+
/// let mut v = Box::new(0i32);
1531+
///
1532+
/// unsafe {
1533+
/// // Leaks the previously held value by overwriting the `Box<T>` with
1534+
/// // a null pointer.
1535+
/// ptr::write_bytes(&mut v as *mut Box<i32>, 0, 1);
1536+
/// }
1537+
///
1538+
/// // At this point, using or dropping `v` results in undefined behavior.
1539+
/// // drop(v); // ERROR
1540+
///
1541+
/// // Even leaking `v` "uses" it, and hence is undefined behavior.
1542+
/// // mem::forget(v); // ERROR
1543+
///
1544+
/// // In fact, `v` is invalid according to basic type layout invariants, so *any*
1545+
/// // operation touching it is undefined behavior.
1546+
/// // let v2 = v; // ERROR
1547+
///
1548+
/// unsafe {
1549+
/// // Let us instead put in a valid value
1550+
/// ptr::write(&mut v as *mut Box<i32>, Box::new(42i32));
1551+
/// }
1552+
///
1553+
/// // Now the box is fine
1554+
/// assert_eq!(*v, 42);
1555+
/// ```
1556+
#[stable(feature = "rust1", since = "1.0.0")]
1557+
#[inline]
1558+
pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
1559+
real_intrinsics::write_bytes(dst, val, count)
1560+
}

0 commit comments

Comments
 (0)
Please sign in to comment.