commit
42eeb75a1f
9 changed files with 201 additions and 40 deletions
2
build.sh
2
build.sh
|
|
@ -41,4 +41,4 @@ gcc target/out/mini_core.o target/out/mini_core_hello_world.o -o target/out/mini
|
|||
./target/out/mini_core_hello_world
|
||||
|
||||
$RUSTC target/libcore/src/libcore/lib.rs --color=always --crate-type lib -Cincremental=target/incremental 2>&1 | (head -n 20; echo "===="; tail -n 1000)
|
||||
cat target/out/log.txt | sort | uniq -c | grep -v "rval unsize move" | grep -v "rval len"
|
||||
cat target/out/log.txt | sort | uniq -c
|
||||
|
|
|
|||
|
|
@ -141,9 +141,9 @@ unsafe fn call_uninit() -> u8 {
|
|||
}
|
||||
|
||||
// TODO: enable when fat pointers are supported
|
||||
/*unsafe fn deref_str_ptr(s: *const str) -> &'static str {
|
||||
unsafe fn deref_str_ptr(s: *const str) -> &'static str {
|
||||
&*s
|
||||
}*/
|
||||
}
|
||||
|
||||
fn use_array(arr: [u8; 3]) -> u8 {
|
||||
arr[1]
|
||||
|
|
@ -153,6 +153,10 @@ fn repeat_array() -> [u8; 3] {
|
|||
[0; 3]
|
||||
}
|
||||
|
||||
fn array_as_slice(arr: &[u8; 3]) -> &[u8] {
|
||||
arr
|
||||
}
|
||||
|
||||
/*unsafe fn use_ctlz_nonzero(a: u16) -> u16 {
|
||||
intrinsics::ctlz_nonzero(a)
|
||||
}*/
|
||||
|
|
@ -176,3 +180,7 @@ fn make_array() -> [u8; 3] {
|
|||
fn some_promoted_tuple() -> &'static (&'static str, &'static str) {
|
||||
&("abc", "some")
|
||||
}
|
||||
|
||||
fn index_slice(s: &[u8]) -> u8 {
|
||||
s[2]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,3 +207,11 @@ impl<T> Index<usize> for [T; 3] {
|
|||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ static NUM_REF: &'static u8 = unsafe { &NUM };
|
|||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let (ptr, _): (*const u8, usize) = intrinsics::transmute("Hello!\0");
|
||||
let slice: &[u8] = b"Hello!\0" as &[u8; 7];
|
||||
let ptr: *const u8 = slice as *const [u8] as *const u8;
|
||||
puts(ptr);
|
||||
}
|
||||
|
||||
|
|
|
|||
13
src/abi.rs
13
src/abi.rs
|
|
@ -28,6 +28,11 @@ fn get_pass_mode<'a, 'tcx: 'a>(
|
|||
ty: Ty<'tcx>,
|
||||
is_return: bool,
|
||||
) -> PassMode {
|
||||
assert!(
|
||||
!tcx.layout_of(ParamEnv::reveal_all().and(ty))
|
||||
.unwrap()
|
||||
.is_unsized()
|
||||
);
|
||||
if ty.sty == tcx.mk_nil().sty {
|
||||
if is_return {
|
||||
//if false {
|
||||
|
|
@ -312,7 +317,7 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
|
|||
//unimplemented!("pass mode nopass");
|
||||
fx.local_map.insert(
|
||||
RETURN_PLACE,
|
||||
CPlace::Addr(null, fx.layout_of(fx.return_type())),
|
||||
CPlace::Addr(null, None, fx.layout_of(fx.return_type())),
|
||||
);
|
||||
}
|
||||
PassMode::ByVal(ret_ty) => {
|
||||
|
|
@ -321,8 +326,10 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
|
|||
.insert(RETURN_PLACE, CPlace::Var(RETURN_PLACE, ret_layout));
|
||||
}
|
||||
PassMode::ByRef => {
|
||||
fx.local_map
|
||||
.insert(RETURN_PLACE, CPlace::Addr(ret_param.unwrap(), ret_layout));
|
||||
fx.local_map.insert(
|
||||
RETURN_PLACE,
|
||||
CPlace::Addr(ret_param.unwrap(), None, ret_layout),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
24
src/base.rs
24
src/base.rs
|
|
@ -309,8 +309,7 @@ fn trans_stmt<'a, 'tcx: 'a>(
|
|||
}
|
||||
Rvalue::Ref(_, _, place) => {
|
||||
let place = trans_place(fx, place);
|
||||
let addr = place.expect_addr();
|
||||
lval.write_cvalue(fx, CValue::ByVal(addr, dest_layout));
|
||||
place.write_place_ref(fx, lval);
|
||||
}
|
||||
Rvalue::BinaryOp(bin_op, lhs, rhs) => {
|
||||
let ty = fx.monomorphize(&lhs.ty(&fx.mir.local_decls, fx.tcx));
|
||||
|
|
@ -459,7 +458,8 @@ fn trans_stmt<'a, 'tcx: 'a>(
|
|||
unimplemented!("rval closure_fn_ptr {:?} {:?}", operand, ty)
|
||||
}
|
||||
Rvalue::Cast(CastKind::Unsize, operand, ty) => {
|
||||
unimpl!("rval unsize {:?} {:?}", operand, ty);
|
||||
let operand = trans_operand(fx, operand);
|
||||
operand.unsize_value(fx, lval);
|
||||
}
|
||||
Rvalue::Discriminant(place) => {
|
||||
let place = trans_place(fx, place).to_cvalue(fx);
|
||||
|
|
@ -474,7 +474,15 @@ fn trans_stmt<'a, 'tcx: 'a>(
|
|||
to.write_cvalue(fx, operand);
|
||||
}
|
||||
}
|
||||
Rvalue::Len(lval) => unimpl!("rval len {:?}", lval),
|
||||
Rvalue::Len(place) => {
|
||||
let place = trans_place(fx, place);
|
||||
let size = match place {
|
||||
CPlace::Addr(_, size, _) => size.unwrap(),
|
||||
CPlace::Var(_, _) => unreachable!(),
|
||||
};
|
||||
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::SizeOf, ty) => {
|
||||
assert!(
|
||||
|
|
@ -893,13 +901,7 @@ pub fn trans_place<'a, 'tcx: 'a>(
|
|||
Place::Projection(projection) => {
|
||||
let base = trans_place(fx, &projection.base);
|
||||
match projection.elem {
|
||||
ProjectionElem::Deref => {
|
||||
let layout = fx.layout_of(place.ty(&*fx.mir, fx.tcx).to_ty(fx.tcx));
|
||||
if layout.is_unsized() {
|
||||
unimpl!("Unsized places are not yet implemented");
|
||||
}
|
||||
CPlace::Addr(base.to_cvalue(fx).load_value(fx), layout)
|
||||
}
|
||||
ProjectionElem::Deref => base.place_deref(fx),
|
||||
ProjectionElem::Field(field, _ty) => base.place_field(fx, field),
|
||||
ProjectionElem::Index(local) => {
|
||||
let index = fx.get_local_place(local).to_cvalue(fx).load_value(fx);
|
||||
|
|
|
|||
174
src/common.rs
174
src/common.rs
|
|
@ -19,6 +19,24 @@ pub fn pointer_ty(tcx: TyCtxt) -> types::Type {
|
|||
}
|
||||
}
|
||||
|
||||
fn scalar_to_cton_type(tcx: TyCtxt, scalar: &Scalar) -> Type {
|
||||
match scalar.value.size(tcx).bits() {
|
||||
8 => types::I8,
|
||||
16 => types::I16,
|
||||
32 => types::I32,
|
||||
64 => types::I64,
|
||||
size => bug!("Unsupported scalar size {}", size),
|
||||
}
|
||||
}
|
||||
|
||||
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>,
|
||||
|
|
@ -198,6 +216,43 @@ impl<'tcx> CValue<'tcx> {
|
|||
CValue::ByRef(field_ptr, field_layout)
|
||||
}
|
||||
|
||||
pub fn unsize_value<'a>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, dest: CPlace<'tcx>) {
|
||||
if self.layout().ty == dest.layout().ty {
|
||||
dest.write_cvalue(fx, self); // FIXME this shouldn't happen (rust-lang/rust#53602)
|
||||
return;
|
||||
}
|
||||
match &self.layout().ty.sty {
|
||||
ty::Ref(_, ty, _) | ty::RawPtr(TypeAndMut { ty, mutbl: _ }) => {
|
||||
let (ptr, extra) = match ptr_referee(dest.layout().ty).sty {
|
||||
ty::Slice(slice_elem_ty) => match ty.sty {
|
||||
ty::Array(array_elem_ty, size) => {
|
||||
assert_eq!(slice_elem_ty, array_elem_ty);
|
||||
let ptr = self.load_value(fx);
|
||||
let extra = fx
|
||||
.bcx
|
||||
.ins()
|
||||
.iconst(fx.module.pointer_type(), size.unwrap_usize(fx.tcx) as i64);
|
||||
(ptr, extra)
|
||||
}
|
||||
_ => bug!("unsize non array {:?} to slice", ty),
|
||||
},
|
||||
ty::Dynamic(_, _) => match ty.sty {
|
||||
ty::Dynamic(_, _) => self.load_value_pair(fx),
|
||||
_ => unimpl!("unsize of type ... to {:?}", dest.layout().ty),
|
||||
},
|
||||
_ => bug!(
|
||||
"unsize of type {:?} to {:?}",
|
||||
self.layout().ty,
|
||||
dest.layout().ty
|
||||
),
|
||||
};
|
||||
println!("ty {:?}", self.layout().ty);
|
||||
dest.write_cvalue(fx, CValue::ByValPair(ptr, extra, dest.layout()));
|
||||
}
|
||||
ty => unimpl!("unsize of non ptr {:?}", ty),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_val<'a>(
|
||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
ty: Ty<'tcx>,
|
||||
|
|
@ -224,18 +279,19 @@ impl<'tcx> CValue<'tcx> {
|
|||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum CPlace<'tcx> {
|
||||
Var(Local, TyLayout<'tcx>),
|
||||
Addr(Value, TyLayout<'tcx>),
|
||||
Addr(Value, Option<Value>, TyLayout<'tcx>),
|
||||
}
|
||||
|
||||
impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||
pub fn layout(&self) -> TyLayout<'tcx> {
|
||||
match *self {
|
||||
CPlace::Var(_, layout) | CPlace::Addr(_, layout) => layout,
|
||||
CPlace::Var(_, layout) | CPlace::Addr(_, _, layout) => layout,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn temp(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, ty: Ty<'tcx>) -> CPlace<'tcx> {
|
||||
let layout = fx.layout_of(ty);
|
||||
assert!(!layout.is_unsized());
|
||||
let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
|
||||
kind: StackSlotKind::ExplicitSlot,
|
||||
size: layout.size.bytes() as u32,
|
||||
|
|
@ -245,6 +301,7 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
|||
fx.bcx
|
||||
.ins()
|
||||
.stack_addr(fx.module.pointer_type(), stack_slot, 0),
|
||||
None,
|
||||
layout,
|
||||
)
|
||||
}
|
||||
|
|
@ -255,10 +312,12 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
|||
ty: Ty<'tcx>,
|
||||
) -> CPlace<'tcx> {
|
||||
let layout = fx.layout_of(ty);
|
||||
assert!(!layout.is_unsized());
|
||||
CPlace::Addr(
|
||||
fx.bcx
|
||||
.ins()
|
||||
.stack_addr(fx.module.pointer_type(), stack_slot, 0),
|
||||
None,
|
||||
layout,
|
||||
)
|
||||
}
|
||||
|
|
@ -266,13 +325,17 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
|||
pub fn to_cvalue(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> CValue<'tcx> {
|
||||
match self {
|
||||
CPlace::Var(var, layout) => CValue::ByVal(fx.bcx.use_var(mir_var(var)), layout),
|
||||
CPlace::Addr(addr, layout) => CValue::ByRef(addr, layout),
|
||||
CPlace::Addr(addr, extra, layout) => {
|
||||
assert!(extra.is_none(), "unsized values are not yet supported");
|
||||
CValue::ByRef(addr, layout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_addr(self) -> Value {
|
||||
match self {
|
||||
CPlace::Addr(addr, _layout) => addr,
|
||||
CPlace::Addr(addr, None, _layout) => addr,
|
||||
CPlace::Addr(_, _, _) => bug!("Expected sized CPlace::Addr, found {:?}", self),
|
||||
CPlace::Var(_, _) => bug!("Expected CPlace::Addr, found CPlace::Var"),
|
||||
}
|
||||
}
|
||||
|
|
@ -308,7 +371,7 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
|||
let data = from.load_value(fx);
|
||||
fx.bcx.def_var(mir_var(var), data)
|
||||
}
|
||||
CPlace::Addr(addr, layout) => {
|
||||
CPlace::Addr(addr, None, layout) => {
|
||||
let size = layout.size.bytes() as i32;
|
||||
|
||||
match from {
|
||||
|
|
@ -346,6 +409,7 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
CPlace::Addr(_, _, _) => bug!("Can't write value to unsized place {:?}", self),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -354,11 +418,14 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
|||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
field: mir::Field,
|
||||
) -> CPlace<'tcx> {
|
||||
let base = self.expect_addr();
|
||||
let layout = self.layout();
|
||||
if layout.is_unsized() {
|
||||
unimpl!("unsized place_field");
|
||||
}
|
||||
|
||||
let base = self.expect_addr();
|
||||
let (field_ptr, field_layout) = codegen_field(fx, base, layout, field);
|
||||
CPlace::Addr(field_ptr, field_layout)
|
||||
CPlace::Addr(field_ptr, None, field_layout)
|
||||
}
|
||||
|
||||
pub fn place_index(
|
||||
|
|
@ -366,26 +433,93 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
|||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||
index: Value,
|
||||
) -> CPlace<'tcx> {
|
||||
let addr = self.expect_addr();
|
||||
let layout = self.layout();
|
||||
match layout.ty.sty {
|
||||
ty::Array(elem_ty, _) => {
|
||||
let elem_layout = fx.layout_of(elem_ty);
|
||||
let offset = fx
|
||||
.bcx
|
||||
.ins()
|
||||
.imul_imm(index, elem_layout.size.bytes() as i64);
|
||||
CPlace::Addr(fx.bcx.ins().iadd(addr, offset), elem_layout)
|
||||
let (elem_layout, addr) = match self.layout().ty.sty {
|
||||
ty::Array(elem_ty, _) => (fx.layout_of(elem_ty), self.expect_addr()),
|
||||
ty::Slice(elem_ty) => (
|
||||
fx.layout_of(elem_ty),
|
||||
match self {
|
||||
CPlace::Addr(addr, _, _) => addr,
|
||||
CPlace::Var(_, _) => bug!("Expected CPlace::Addr found CPlace::Var"),
|
||||
},
|
||||
),
|
||||
_ => bug!("place_index({:?})", self.layout().ty),
|
||||
};
|
||||
|
||||
let offset = fx
|
||||
.bcx
|
||||
.ins()
|
||||
.imul_imm(index, elem_layout.size.bytes() as i64);
|
||||
|
||||
CPlace::Addr(fx.bcx.ins().iadd(addr, offset), None, elem_layout)
|
||||
}
|
||||
|
||||
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));
|
||||
if !inner_layout.is_unsized() {
|
||||
CPlace::Addr(self.to_cvalue(fx).load_value(fx), None, inner_layout)
|
||||
} else {
|
||||
match self.layout().abi {
|
||||
Abi::ScalarPair(ref a, ref b) => {
|
||||
let addr = self.expect_addr();
|
||||
let ptr =
|
||||
fx.bcx
|
||||
.ins()
|
||||
.load(scalar_to_cton_type(fx.tcx, a), MemFlags::new(), addr, 0);
|
||||
let extra = fx.bcx.ins().load(
|
||||
scalar_to_cton_type(fx.tcx, b),
|
||||
MemFlags::new(),
|
||||
addr,
|
||||
a.value.size(fx.tcx).bytes() as u32 as i32,
|
||||
);
|
||||
println!(
|
||||
"unsized deref: ptr: {:?} extra: {:?} self: {:?}",
|
||||
ptr, extra, self
|
||||
);
|
||||
CPlace::Addr(ptr, Some(extra), inner_layout)
|
||||
}
|
||||
_ => bug!(
|
||||
"Fat ptr doesn't have abi ScalarPair, but it has {:?}",
|
||||
self.layout().abi
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_place_ref(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, dest: CPlace<'tcx>) {
|
||||
if !self.layout().is_unsized() {
|
||||
let ptr = CValue::ByVal(self.expect_addr(), dest.layout());
|
||||
dest.write_cvalue(fx, ptr);
|
||||
} else {
|
||||
match self {
|
||||
CPlace::Var(_, _) => bug!("expected CPlace::Addr found CPlace::Var"),
|
||||
CPlace::Addr(value, extra, _) => match dest.layout().abi {
|
||||
Abi::ScalarPair(ref a, _) => {
|
||||
fx.bcx
|
||||
.ins()
|
||||
.store(MemFlags::new(), value, dest.expect_addr(), 0);
|
||||
fx.bcx.ins().store(
|
||||
MemFlags::new(),
|
||||
extra.expect("unsized type without metadata"),
|
||||
dest.expect_addr(),
|
||||
a.value.size(fx.tcx).bytes() as u32 as i32,
|
||||
);
|
||||
}
|
||||
_ => bug!(
|
||||
"Non ScalarPair abi {:?} in write_place_ref dest",
|
||||
dest.layout().abi
|
||||
),
|
||||
},
|
||||
}
|
||||
ty::Slice(_elem_ty) => unimplemented!("place_index(TySlice)"),
|
||||
_ => bug!("place_index({:?})", layout.ty),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
|
||||
match self {
|
||||
CPlace::Var(var, _) => CPlace::Var(var, layout),
|
||||
CPlace::Addr(addr, _) => CPlace::Addr(addr, layout),
|
||||
CPlace::Addr(addr, extra, _) => {
|
||||
assert!(!layout.is_unsized());
|
||||
CPlace::Addr(addr, extra, layout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -179,7 +179,8 @@ fn cplace_for_dataid<'a, 'tcx: 'a>(
|
|||
.ins()
|
||||
.global_value(fx.module.pointer_type(), local_data_id);
|
||||
let layout = fx.layout_of(fx.monomorphize(&ty));
|
||||
CPlace::Addr(global_ptr, layout)
|
||||
assert!(!layout.is_unsized(), "unsized statics aren't supported");
|
||||
CPlace::Addr(global_ptr, None, layout)
|
||||
}
|
||||
|
||||
fn define_all_allocs<'a, 'tcx: 'a, B: Backend + 'a>(
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ mod prelude {
|
|||
pub use rustc::mir::interpret::AllocId;
|
||||
pub use rustc::mir::*;
|
||||
pub use rustc::session::{config::CrateType, Session};
|
||||
pub use rustc::ty::layout::{self, LayoutOf, Size, TyLayout};
|
||||
pub use rustc::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyLayout};
|
||||
pub use rustc::ty::{
|
||||
self, subst::Substs, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt,
|
||||
TypeAndMut, TypeFoldable,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue