Implement intrinsic min_align_of_val

This commit is contained in:
bjorn3 2018-09-15 11:14:27 +02:00
parent 6e87a4f16d
commit 1f1746e2d3
4 changed files with 62 additions and 25 deletions

View file

@ -222,6 +222,8 @@ pub mod intrinsics {
pub fn abort() -> !;
pub fn size_of<T>() -> usize;
pub fn size_of_val<T: ?::Sized>(val: &T) -> usize;
pub fn min_align_of<T>() -> usize;
pub fn min_align_of_val<T: ?::Sized>(val: &T) -> usize;
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
pub fn transmute<T, U>(e: T) -> U;
pub fn uninit<T>() -> T;

View file

@ -86,6 +86,22 @@ fn start<T: Termination + 'static>(
static mut NUM: u8 = 6 * 7;
static NUM_REF: &'static u8 = unsafe { &NUM };
macro_rules! assert {
($e:expr) => {
if !$e {
panic(&(stringify!(! $e), file!(), line!(), 0));
}
};
}
macro_rules! assert_eq {
($l:expr, $r: expr) => {
if $l != $r {
panic(&(stringify!($l != $r), file!(), line!(), 0));
}
}
}
fn main() {
unsafe {
let hello: &[u8] = b"Hello\0" as &[u8; 6];
@ -99,34 +115,23 @@ fn main() {
puts(*world as *const str as *const u8);
}
if intrinsics::size_of_val(hello) as u8 != 6 {
panic(&("", "", 0, 0));
};
assert_eq!(intrinsics::size_of_val(hello) as u8, 6);
let chars = &['C', 'h', 'a', 'r', 's'];
let chars = chars as &[char];
if intrinsics::size_of_val(chars) as u8 != 4 * 5 {
panic(&("", "", 0, 0));
}
assert_eq!(intrinsics::size_of_val(chars) as u8, 4 * 5);
let a: &dyn SomeTrait = &"abc\0";
a.object_safe();
if intrinsics::size_of_val(a) as u8 != 16 {
panic(&("", "", 0, 0));
}
assert_eq!(intrinsics::size_of_val(a) as u8, 16);
assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4);
if intrinsics::size_of_val(&0u32) as u8 != 4 {
panic(&("", "", 0, 0));
}
assert_eq!(intrinsics::min_align_of::<u16>() as u8, 2);
assert_eq!(intrinsics::min_align_of_val(&a) as u8, intrinsics::min_align_of::<&str>() as u8);
if intrinsics::needs_drop::<u8>() {
panic(&("", "", 0, 0));
}
if !intrinsics::needs_drop::<NoisyDrop>() {
panic(&("", "", 0, 0));
}
assert!(!intrinsics::needs_drop::<u8>());
assert!(intrinsics::needs_drop::<NoisyDrop>());
}
let _ = NoisyDrop {

View file

@ -675,18 +675,34 @@ fn codegen_intrinsic_call<'a, 'tcx: 'a>(
};
ret.write_cvalue(fx, CValue::ByVal(size, usize_layout));
}
"type_id" => {
assert_eq!(args.len(), 0);
let type_id = fx.tcx.type_id_hash(substs.type_at(0));
let type_id = CValue::const_val(fx, u64_layout.ty, type_id as i64);
ret.write_cvalue(fx, type_id);
}
"min_align_of" => {
assert_eq!(args.len(), 0);
let min_align = fx.layout_of(substs.type_at(0)).align.abi();
let min_align = CValue::const_val(fx, usize_layout.ty, min_align as i64);
ret.write_cvalue(fx, min_align);
}
"min_align_of_val" => {
assert_eq!(args.len(), 1);
let layout = fx.layout_of(substs.type_at(0));
let align = match &layout.ty.sty {
_ if !layout.is_unsized() => {
fx.bcx.ins().iconst(fx.module.pointer_type(), layout.align.abi() as i64)
}
ty::Slice(elem) => {
let align = fx.layout_of(elem).align.abi() as i64;
fx.bcx.ins().iconst(fx.module.pointer_type(), align)
}
ty::Dynamic(..) => crate::vtable::min_align_of_obj(fx, args[0]),
ty => unimplemented!("min_align_of_val for {:?}", ty),
};
ret.write_cvalue(fx, CValue::ByVal(align, usize_layout));
}
"type_id" => {
assert_eq!(args.len(), 0);
let type_id = fx.tcx.type_id_hash(substs.type_at(0));
let type_id = CValue::const_val(fx, u64_layout.ty, type_id as i64);
ret.write_cvalue(fx, type_id);
}
_ if intrinsic.starts_with("unchecked_") => {
assert_eq!(args.len(), 2);
let bin_op = match intrinsic {

View file

@ -20,6 +20,20 @@ pub fn size_of_obj<'a, 'tcx: 'a>(
)
}
pub fn min_align_of_obj<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
val: CValue<'tcx>,
) -> Value {
let (_ptr, vtable) = val.load_value_pair(fx);
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
fx.bcx.ins().load(
pointer_ty(fx.tcx),
MemFlags::new(),
vtable,
(ALIGN_INDEX * usize_size) as i32,
)
}
pub fn get_ptr_and_method_ref<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
arg: CValue<'tcx>,