From 8adc744645f72dce8d3030b3c3cd282c14e8a6de Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 4 Sep 2018 19:04:25 +0200 Subject: [PATCH] Implement Box rvalue --- Readme.md | 1 - examples/mini_core.rs | 11 +++++++++++ examples/mini_core_hello_world.rs | 6 ++++-- src/base.rs | 23 ++++++++++++++++++++++- src/common.rs | 21 ++++++++++----------- 5 files changed, 47 insertions(+), 15 deletions(-) diff --git a/Readme.md b/Readme.md index 7f0e8d8b3b7..3c07f08f951 100644 --- a/Readme.md +++ b/Readme.md @@ -40,7 +40,6 @@ $ ./build.sh * Unsized types * Slice indexing * Sub slice -* Some rvalue's * Inline assembly * Custom sections diff --git a/examples/mini_core.rs b/examples/mini_core.rs index 7b4eccb5713..75059743b9d 100644 --- a/examples/mini_core.rs +++ b/examples/mini_core.rs @@ -45,6 +45,7 @@ unsafe impl Sync for i32 {} unsafe impl Sync for isize {} unsafe impl Sync for char {} unsafe impl<'a, T: ?Sized> Sync for &'a T {} +unsafe impl Sync for [u8; 16] {} #[lang = "freeze"] trait Freeze {} @@ -186,6 +187,16 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { drop_in_place(to_drop); } +#[lang = "owned_box"] +pub struct Box(*mut T); + +static mut MY_TINY_HEAP: [u8; 16] = [0; 16]; + +#[lang = "exchange_malloc"] +unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { + &mut MY_TINY_HEAP as *mut [u8; 16] as *mut u8 +} + pub mod intrinsics { extern "rust-intrinsic" { pub fn abort() -> !; diff --git a/examples/mini_core_hello_world.rs b/examples/mini_core_hello_world.rs index c775beef2f0..a8297fe7613 100644 --- a/examples/mini_core_hello_world.rs +++ b/examples/mini_core_hello_world.rs @@ -1,6 +1,6 @@ // Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs -#![feature(no_core, unboxed_closures, start, lang_items)] +#![feature(no_core, unboxed_closures, start, lang_items, box_syntax)] #![no_core] #![allow(dead_code)] @@ -43,9 +43,11 @@ static NUM_REF: &'static u8 = unsafe { &NUM }; fn main() { unsafe { - let slice: &[u8] = b"Hello!\0" as &[u8; 7]; + let slice: &[u8] = b"Hello\0" as &[u8; 6]; let ptr: *const u8 = slice as *const [u8] as *const u8; + let world = box "World!\0"; puts(ptr); + puts(*world as *const str as *const u8); } //panic(&("panic msg", "abc.rs", 0, 43)); diff --git a/src/base.rs b/src/base.rs index 10452757281..cfe44f2f689 100644 --- a/src/base.rs +++ b/src/base.rs @@ -488,7 +488,28 @@ fn trans_stmt<'a, 'tcx: 'a>( let usize_layout = fx.layout_of(fx.tcx.types.usize); lval.write_cvalue(fx, CValue::ByVal(size, usize_layout)); } - Rvalue::NullaryOp(NullOp::Box, ty) => unimplemented!("rval box {:?}", ty), + Rvalue::NullaryOp(NullOp::Box, content_ty) => { + use rustc::middle::lang_items::ExchangeMallocFnLangItem; + + let usize_type = fx.cton_type(fx.tcx.types.usize).unwrap(); + let (size, align) = fx.layout_of(content_ty).size_and_align(); + let llsize = fx.bcx.ins().iconst(usize_type, size.bytes() as i64); + let llalign = fx.bcx.ins().iconst(usize_type, align.abi() as i64); + let box_layout = fx.layout_of(fx.tcx.mk_box(content_ty)); + + // Allocate space: + let def_id = match fx.tcx.lang_items().require(ExchangeMallocFnLangItem) { + Ok(id) => id, + Err(s) => { + fx.tcx.sess.fatal(&format!("allocation of `{}` {}", box_layout.ty, s)); + } + }; + let instance = ty::Instance::mono(fx.tcx, def_id); + let func_ref = fx.get_function_ref(instance); + let call = fx.bcx.ins().call(func_ref, &[llsize, llalign]); + let ptr = fx.bcx.inst_results(call)[0]; + lval.write_cvalue(fx, CValue::ByVal(ptr, box_layout)); + }, Rvalue::NullaryOp(NullOp::SizeOf, ty) => { assert!( lval.layout() diff --git a/src/common.rs b/src/common.rs index 3c7afe774af..7081511b19b 100644 --- a/src/common.rs +++ b/src/common.rs @@ -29,14 +29,6 @@ fn scalar_to_cton_type(tcx: TyCtxt, scalar: &Scalar) -> Type { } } -fn ptr_referee<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> { - match ty.sty { - ty::Ref(_, ty, _) => ty, - ty::RawPtr(TypeAndMut { ty, mutbl: _ }) => ty, - _ => bug!("{:?}", ty), - } -} - pub fn cton_type_from_ty<'a, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>, @@ -153,7 +145,14 @@ impl<'tcx> CValue<'tcx> { CValue::ByRef(addr, layout) => { let cton_ty = fx .cton_type(layout.ty) - .expect(&format!("load_value of type {:?}", layout.ty)); + .unwrap_or_else(|| { + if layout.ty.is_box() && !fx.layout_of(layout.ty.builtin_deref(true).unwrap().ty).is_unsized() { + // Consider sized box to be a ptr + pointer_ty(fx.tcx) + } else { + panic!("load_value of type {:?}", layout.ty); + } + }); fx.bcx.ins().load(cton_ty, MemFlags::new(), addr, 0) } CValue::ByVal(value, _layout) => value, @@ -223,7 +222,7 @@ impl<'tcx> CValue<'tcx> { } match &self.layout().ty.sty { ty::Ref(_, ty, _) | ty::RawPtr(TypeAndMut { ty, mutbl: _ }) => { - let (ptr, extra) = match ptr_referee(dest.layout().ty).sty { + let (ptr, extra) = match dest.layout().ty.builtin_deref(true).unwrap().ty.sty { ty::Slice(slice_elem_ty) => match ty.sty { ty::Array(array_elem_ty, size) => { assert_eq!(slice_elem_ty, array_elem_ty); @@ -453,7 +452,7 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> { } pub fn place_deref(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> CPlace<'tcx> { - let inner_layout = fx.layout_of(ptr_referee(self.layout().ty)); + let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap().ty); if !inner_layout.is_unsized() { CPlace::Addr(self.to_cvalue(fx).load_value(fx), None, inner_layout) } else {