Implement Box rvalue

This commit is contained in:
bjorn3 2018-09-04 19:04:25 +02:00
parent e407f39ba8
commit 8adc744645
5 changed files with 47 additions and 15 deletions

View file

@ -40,7 +40,6 @@ $ ./build.sh
* Unsized types
* Slice indexing
* Sub slice
* Some rvalue's
* Inline assembly
* Custom sections

View file

@ -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<T: ?Sized>(to_drop: *mut T) {
drop_in_place(to_drop);
}
#[lang = "owned_box"]
pub struct Box<T>(*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() -> !;

View file

@ -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));

View file

@ -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()

View file

@ -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 {