Support unsized types
This commit is contained in:
parent
0117b7872a
commit
b5082f7da8
6 changed files with 123 additions and 25 deletions
|
@ -141,9 +141,9 @@ unsafe fn call_uninit() -> u8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: enable when fat pointers are supported
|
// 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
|
&*s
|
||||||
}*/
|
}
|
||||||
|
|
||||||
fn use_array(arr: [u8; 3]) -> u8 {
|
fn use_array(arr: [u8; 3]) -> u8 {
|
||||||
arr[1]
|
arr[1]
|
||||||
|
|
13
src/abi.rs
13
src/abi.rs
|
@ -28,6 +28,11 @@ fn get_pass_mode<'a, 'tcx: 'a>(
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
is_return: bool,
|
is_return: bool,
|
||||||
) -> PassMode {
|
) -> PassMode {
|
||||||
|
assert!(
|
||||||
|
!tcx.layout_of(ParamEnv::reveal_all().and(ty))
|
||||||
|
.unwrap()
|
||||||
|
.is_unsized()
|
||||||
|
);
|
||||||
if ty.sty == tcx.mk_nil().sty {
|
if ty.sty == tcx.mk_nil().sty {
|
||||||
if is_return {
|
if is_return {
|
||||||
//if false {
|
//if false {
|
||||||
|
@ -312,7 +317,7 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
|
||||||
//unimplemented!("pass mode nopass");
|
//unimplemented!("pass mode nopass");
|
||||||
fx.local_map.insert(
|
fx.local_map.insert(
|
||||||
RETURN_PLACE,
|
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) => {
|
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));
|
.insert(RETURN_PLACE, CPlace::Var(RETURN_PLACE, ret_layout));
|
||||||
}
|
}
|
||||||
PassMode::ByRef => {
|
PassMode::ByRef => {
|
||||||
fx.local_map
|
fx.local_map.insert(
|
||||||
.insert(RETURN_PLACE, CPlace::Addr(ret_param.unwrap(), ret_layout));
|
RETURN_PLACE,
|
||||||
|
CPlace::Addr(ret_param.unwrap(), None, ret_layout),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
src/base.rs
11
src/base.rs
|
@ -309,8 +309,7 @@ fn trans_stmt<'a, 'tcx: 'a>(
|
||||||
}
|
}
|
||||||
Rvalue::Ref(_, _, place) => {
|
Rvalue::Ref(_, _, place) => {
|
||||||
let place = trans_place(fx, place);
|
let place = trans_place(fx, place);
|
||||||
let addr = place.expect_addr();
|
place.write_place_ref(fx, lval);
|
||||||
lval.write_cvalue(fx, CValue::ByVal(addr, dest_layout));
|
|
||||||
}
|
}
|
||||||
Rvalue::BinaryOp(bin_op, lhs, rhs) => {
|
Rvalue::BinaryOp(bin_op, lhs, rhs) => {
|
||||||
let ty = fx.monomorphize(&lhs.ty(&fx.mir.local_decls, fx.tcx));
|
let ty = fx.monomorphize(&lhs.ty(&fx.mir.local_decls, fx.tcx));
|
||||||
|
@ -893,13 +892,7 @@ pub fn trans_place<'a, 'tcx: 'a>(
|
||||||
Place::Projection(projection) => {
|
Place::Projection(projection) => {
|
||||||
let base = trans_place(fx, &projection.base);
|
let base = trans_place(fx, &projection.base);
|
||||||
match projection.elem {
|
match projection.elem {
|
||||||
ProjectionElem::Deref => {
|
ProjectionElem::Deref => base.place_deref(fx),
|
||||||
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::Field(field, _ty) => base.place_field(fx, field),
|
ProjectionElem::Field(field, _ty) => base.place_field(fx, field),
|
||||||
ProjectionElem::Index(local) => {
|
ProjectionElem::Index(local) => {
|
||||||
let index = fx.get_local_place(local).to_cvalue(fx).load_value(fx);
|
let index = fx.get_local_place(local).to_cvalue(fx).load_value(fx);
|
||||||
|
|
115
src/common.rs
115
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>(
|
pub fn cton_type_from_ty<'a, 'tcx: 'a>(
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
|
@ -224,18 +242,19 @@ impl<'tcx> CValue<'tcx> {
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum CPlace<'tcx> {
|
pub enum CPlace<'tcx> {
|
||||||
Var(Local, TyLayout<'tcx>),
|
Var(Local, TyLayout<'tcx>),
|
||||||
Addr(Value, TyLayout<'tcx>),
|
Addr(Value, Option<Value>, TyLayout<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||||
pub fn layout(&self) -> TyLayout<'tcx> {
|
pub fn layout(&self) -> TyLayout<'tcx> {
|
||||||
match *self {
|
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> {
|
pub fn temp(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, ty: Ty<'tcx>) -> CPlace<'tcx> {
|
||||||
let layout = fx.layout_of(ty);
|
let layout = fx.layout_of(ty);
|
||||||
|
assert!(!layout.is_unsized());
|
||||||
let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
|
let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
|
||||||
kind: StackSlotKind::ExplicitSlot,
|
kind: StackSlotKind::ExplicitSlot,
|
||||||
size: layout.size.bytes() as u32,
|
size: layout.size.bytes() as u32,
|
||||||
|
@ -245,6 +264,7 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||||
fx.bcx
|
fx.bcx
|
||||||
.ins()
|
.ins()
|
||||||
.stack_addr(fx.module.pointer_type(), stack_slot, 0),
|
.stack_addr(fx.module.pointer_type(), stack_slot, 0),
|
||||||
|
None,
|
||||||
layout,
|
layout,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -255,10 +275,12 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> CPlace<'tcx> {
|
) -> CPlace<'tcx> {
|
||||||
let layout = fx.layout_of(ty);
|
let layout = fx.layout_of(ty);
|
||||||
|
assert!(!layout.is_unsized());
|
||||||
CPlace::Addr(
|
CPlace::Addr(
|
||||||
fx.bcx
|
fx.bcx
|
||||||
.ins()
|
.ins()
|
||||||
.stack_addr(fx.module.pointer_type(), stack_slot, 0),
|
.stack_addr(fx.module.pointer_type(), stack_slot, 0),
|
||||||
|
None,
|
||||||
layout,
|
layout,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -266,13 +288,17 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||||
pub fn to_cvalue(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> CValue<'tcx> {
|
pub fn to_cvalue(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> CValue<'tcx> {
|
||||||
match self {
|
match self {
|
||||||
CPlace::Var(var, layout) => CValue::ByVal(fx.bcx.use_var(mir_var(var)), layout),
|
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 {
|
pub fn expect_addr(self) -> Value {
|
||||||
match self {
|
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"),
|
CPlace::Var(_, _) => bug!("Expected CPlace::Addr, found CPlace::Var"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,7 +334,7 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||||
let data = from.load_value(fx);
|
let data = from.load_value(fx);
|
||||||
fx.bcx.def_var(mir_var(var), data)
|
fx.bcx.def_var(mir_var(var), data)
|
||||||
}
|
}
|
||||||
CPlace::Addr(addr, layout) => {
|
CPlace::Addr(addr, None, layout) => {
|
||||||
let size = layout.size.bytes() as i32;
|
let size = layout.size.bytes() as i32;
|
||||||
|
|
||||||
match from {
|
match from {
|
||||||
|
@ -346,6 +372,7 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CPlace::Addr(_, _, _) => bug!("Can't write value to unsized place {:?}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,11 +381,14 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||||
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||||
field: mir::Field,
|
field: mir::Field,
|
||||||
) -> CPlace<'tcx> {
|
) -> CPlace<'tcx> {
|
||||||
let base = self.expect_addr();
|
|
||||||
let layout = self.layout();
|
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);
|
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(
|
pub fn place_index(
|
||||||
|
@ -368,6 +398,10 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||||
) -> CPlace<'tcx> {
|
) -> CPlace<'tcx> {
|
||||||
let addr = self.expect_addr();
|
let addr = self.expect_addr();
|
||||||
let layout = self.layout();
|
let layout = self.layout();
|
||||||
|
if layout.is_unsized() {
|
||||||
|
unimpl!("unsized place_field");
|
||||||
|
}
|
||||||
|
|
||||||
match layout.ty.sty {
|
match layout.ty.sty {
|
||||||
ty::Array(elem_ty, _) => {
|
ty::Array(elem_ty, _) => {
|
||||||
let elem_layout = fx.layout_of(elem_ty);
|
let elem_layout = fx.layout_of(elem_ty);
|
||||||
|
@ -375,17 +409,80 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
|
||||||
.bcx
|
.bcx
|
||||||
.ins()
|
.ins()
|
||||||
.imul_imm(index, elem_layout.size.bytes() as i64);
|
.imul_imm(index, elem_layout.size.bytes() as i64);
|
||||||
CPlace::Addr(fx.bcx.ins().iadd(addr, offset), elem_layout)
|
CPlace::Addr(fx.bcx.ins().iadd(addr, offset), None, elem_layout)
|
||||||
}
|
}
|
||||||
ty::Slice(_elem_ty) => unimplemented!("place_index(TySlice)"),
|
ty::Slice(_elem_ty) => unimplemented!("place_index(TySlice)"),
|
||||||
_ => bug!("place_index({:?})", layout.ty),
|
_ => bug!("place_index({:?})", layout.ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
|
pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
|
||||||
match self {
|
match self {
|
||||||
CPlace::Var(var, _) => CPlace::Var(var, layout),
|
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()
|
.ins()
|
||||||
.global_value(fx.module.pointer_type(), local_data_id);
|
.global_value(fx.module.pointer_type(), local_data_id);
|
||||||
let layout = fx.layout_of(fx.monomorphize(&ty));
|
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>(
|
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::interpret::AllocId;
|
||||||
pub use rustc::mir::*;
|
pub use rustc::mir::*;
|
||||||
pub use rustc::session::{config::CrateType, Session};
|
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::{
|
pub use rustc::ty::{
|
||||||
self, subst::Substs, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt,
|
self, subst::Substs, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt,
|
||||||
TypeAndMut, TypeFoldable,
|
TypeAndMut, TypeFoldable,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue