Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

gccrs#4620: Add write_bytes and arith_offset

Link: Rust-GCC/gccrs#4620

Definition:

#![allow(unused)]
fn main() {
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
}
#![allow(unused)]
fn main() {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
    extern "rust-intrinsic" {
        fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
    }

    debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");

    // SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
    unsafe { write_bytes(dst, val, count) }
}

}

Objective

This PR implements arith_offset and write_bytes compiler intrinsics.

Changes Made

  • write_bytes: Lowered to GCC’s __builtin_memset.
  • arith_offset: Lowered using GCC’s POINTER_PLUS_EXPR.

Why is this needed for alloc?

The alloc crate relies heavily on these intrinsics for raw memory manipulation. arith_offset is required for pointer arithmetic (calculating offsets for data structures like Vec), and write_bytes is used to quickly set memory regions to a specific value.

Test Case

fn try_arith_offset() -> i32 {
    let base_addr: usize = 0;
    let ptr = base_addr as *const u64;

    let wrap_ptr = ptr.wrapping_offset(-1);

    if wrap_ptr as isize == -8_isize {
        0
    } else {
        1
    }
}

fn try_write_bytes() -> i32 {
    let mut x: u32 = 0;
    unsafe {
        core::ptr::write_bytes(&mut x as *mut u32, 0xEC_u8, 1);
    }
    if x == 0xECECECEC_u32 {
        0
    } else {
        1
    }
}

fn main() {
    println!("arith_offset result: {}", try_arith_offset());
    println!("write_bytes result: {}", try_write_bytes());
}

The arith_offset correctly wraps around using two’s complement arithmetic without undefined behavior. write_bytes successfully acts as a memset, modifying the exact byte pattern of the memory block.