gccrs#4672: Add size_of_val and min_align_of_val intrinsics
Link: Rust-GCC/gccrs#4672
Definition:
#![allow(unused)]
fn main() {
#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
}
#![allow(unused)]
fn main() {
#[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
}
Objective
This PR adds the size_of_val and min_align_of_val intrinsics. Unlike compile-time intrinsics, these evaluate the size and alignment of a value dynamically at runtime.
Changes Made
Implemented the backend function bodies for these intrinsics. If the passed pointer points to a Dynamically Sized Type (DST, like a trait object or slice), the compiler now correctly fetches the size and alignment information directly from the associated vtable or slice metadata at runtime.
Why is this needed for alloc?
alloc functions need to know the exact memory layout to allocate or deallocate memory correctly. These intrinsics allow alloc to safely handle unsized types dynamically.
Test Case
trait TraitA {
fn foo(&self) {}
}
struct StructA {
_a: i32,
_b: i32,
}
impl TraitA for StructA {}
impl TraitA for u8 {}
fn try_size_of_val() -> i32 {
let val_i32: i32 = 32;
let size_i32 = std::mem::size_of_val(&val_i32);
let val_struct = StructA { _a: 1, _b: 2 };
let size_struct = std::mem::size_of_val(&val_struct);
let arr: [i32; 3] = [10, 20, 30];
let val_slice: &[i32] = &arr;
let size_slice = std::mem::size_of_val(val_slice);
let val_str: &str = "gccrs";
let size_str = std::mem::size_of_val(val_str);
let val_dyn_struct = &val_struct as &dyn TraitA;
let size_dyn_struct = std::mem::size_of_val(val_dyn_struct);
let val_u8: u8 = 7;
let size_u8 = std::mem::size_of_val(&val_u8);
let val_dyn_u8 = &val_u8 as &dyn TraitA;
let size_dyn_u8 = std::mem::size_of_val(val_dyn_u8);
if size_i32 != 4 {
1
} else if size_struct != 8 {
2
} else if size_slice != 12 {
3
} else if size_str != 5 {
4
} else if size_dyn_struct != 8 {
5
} else if size_u8 != 1 {
6
} else if size_dyn_u8 != 1 {
7
} else {
0
}
}
fn main() {
println!("size_of_val result: {}", try_size_of_val());
}
trait TraitA {
fn foo(&self) {}
}
struct StructA {
_a: i32,
_b: i16,
}
impl TraitA for StructA {}
impl TraitA for u8 {}
fn try_min_align_of_val() -> i32 {
let val_i32: i32 = 32;
let align_i32 = std::mem::align_of_val(&val_i32);
let val_struct = StructA { _a: 1, _b: 2 };
let align_struct = std::mem::align_of_val(&val_struct);
let arr: [i32; 3] = [10, 20, 30];
let val_slice: &[i32] = &arr;
let align_slice = std::mem::align_of_val(val_slice);
let val_str: &str = "gccrs";
let align_str = std::mem::align_of_val(val_str);
let val_dyn_struct = &val_struct as &dyn TraitA;
let align_dyn_struct = std::mem::align_of_val(val_dyn_struct);
let val_u8: u8 = 7;
let align_u8 = std::mem::align_of_val(&val_u8);
let val_dyn_u8 = &val_u8 as &dyn TraitA;
let align_dyn_u8 = std::mem::align_of_val(val_dyn_u8);
if align_i32 != 4 {
1
} else if align_struct != 4 {
2
} else if align_slice != 4 {
3
} else if align_str != 1 {
4
} else if align_dyn_struct != 4 {
5
} else if align_u8 != 1 {
6
} else if align_dyn_u8 != 1 {
7
} else {
0
}
}
fn main() {
println!("min_align_of_val result: {}", try_min_align_of_val());
}