From 1f1746e2d35692bed22fa0c6108b09a736cd65cb Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 15 Sep 2018 11:14:27 +0200 Subject: [PATCH] Implement intrinsic min_align_of_val --- examples/mini_core.rs | 2 ++ examples/mini_core_hello_world.rs | 43 +++++++++++++++++-------------- src/abi.rs | 28 +++++++++++++++----- src/vtable.rs | 14 ++++++++++ 4 files changed, 62 insertions(+), 25 deletions(-) diff --git a/examples/mini_core.rs b/examples/mini_core.rs index 6e2e9dd37f6..544f2eceac0 100644 --- a/examples/mini_core.rs +++ b/examples/mini_core.rs @@ -222,6 +222,8 @@ pub mod intrinsics { pub fn abort() -> !; pub fn size_of() -> usize; pub fn size_of_val(val: &T) -> usize; + pub fn min_align_of() -> usize; + pub fn min_align_of_val(val: &T) -> usize; pub fn copy(src: *const T, dst: *mut T, count: usize); pub fn transmute(e: T) -> U; pub fn uninit() -> T; diff --git a/examples/mini_core_hello_world.rs b/examples/mini_core_hello_world.rs index 5948415c929..ff7d7975e27 100644 --- a/examples/mini_core_hello_world.rs +++ b/examples/mini_core_hello_world.rs @@ -86,6 +86,22 @@ fn start( 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::() as u8, 2); + assert_eq!(intrinsics::min_align_of_val(&a) as u8, intrinsics::min_align_of::<&str>() as u8); - if intrinsics::needs_drop::() { - panic(&("", "", 0, 0)); - } - - if !intrinsics::needs_drop::() { - panic(&("", "", 0, 0)); - } + assert!(!intrinsics::needs_drop::()); + assert!(intrinsics::needs_drop::()); } let _ = NoisyDrop { diff --git a/src/abi.rs b/src/abi.rs index bc61ba5a708..21886218962 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -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 { diff --git a/src/vtable.rs b/src/vtable.rs index 4d2382979c9..da9c3765588 100644 --- a/src/vtable.rs +++ b/src/vtable.rs @@ -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>,