1
Fork 0

Fix foreign type handling

This commit is contained in:
bjorn3 2019-09-14 17:53:36 +02:00
parent b267995f39
commit c34ada7cca
4 changed files with 27 additions and 24 deletions

View file

@ -365,6 +365,7 @@ fn trans_stmt<'tcx>(
Rvalue::Cast(CastKind::Misc, operand, to_ty) => { Rvalue::Cast(CastKind::Misc, operand, to_ty) => {
let operand = trans_operand(fx, operand); let operand = trans_operand(fx, operand);
let from_ty = operand.layout().ty; let from_ty = operand.layout().ty;
let to_ty = fx.monomorphize(to_ty);
fn is_fat_ptr<'tcx>( fn is_fat_ptr<'tcx>(
fx: &FunctionCx<'_, 'tcx, impl Backend>, fx: &FunctionCx<'_, 'tcx, impl Backend>,
@ -375,9 +376,7 @@ fn trans_stmt<'tcx>(
|ty::TypeAndMut { |ty::TypeAndMut {
ty: pointee_ty, ty: pointee_ty,
mutbl: _, mutbl: _,
}| { }| has_ptr_meta(fx.tcx, pointee_ty),
fx.layout_of(pointee_ty).is_unsized()
},
) )
.unwrap_or(false) .unwrap_or(false)
} }

View file

@ -60,11 +60,11 @@ pub fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types:
FloatTy::F64 => types::F64, FloatTy::F64 => types::F64,
}, },
ty::FnPtr(_) => pointer_ty(tcx), ty::FnPtr(_) => pointer_ty(tcx),
ty::RawPtr(TypeAndMut { ty, mutbl: _ }) | ty::Ref(_, ty, _) => { ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl: _ }) | ty::Ref(_, pointee_ty, _) => {
if ty.is_sized(tcx.at(DUMMY_SP), ParamEnv::reveal_all()) { if has_ptr_meta(tcx, pointee_ty) {
pointer_ty(tcx)
} else {
return None; return None;
} else {
pointer_ty(tcx)
} }
} }
ty::Param(_) => bug!("ty param {:?}", ty), ty::Param(_) => bug!("ty param {:?}", ty),
@ -72,6 +72,16 @@ pub fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types:
}) })
} }
/// Is a pointer to this type a fat ptr?
pub fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
let ptr_ty = tcx.mk_ptr(TypeAndMut { ty, mutbl: rustc::hir::Mutability::MutImmutable });
match &tcx.layout_of(ParamEnv::reveal_all().and(ptr_ty)).unwrap().abi {
Abi::Scalar(_) => false,
Abi::ScalarPair(_, _) => true,
abi => unreachable!("Abi of ptr to {:?} is {:?}???", ty, abi),
}
}
pub fn codegen_select(bcx: &mut FunctionBuilder, cond: Value, lhs: Value, rhs: Value) -> Value { pub fn codegen_select(bcx: &mut FunctionBuilder, cond: Value, lhs: Value, rhs: Value) -> Value {
let lhs_ty = bcx.func.dfg.value_type(lhs); let lhs_ty = bcx.func.dfg.value_type(lhs);
let rhs_ty = bcx.func.dfg.value_type(rhs); let rhs_ty = bcx.func.dfg.value_type(rhs);

View file

@ -347,14 +347,9 @@ pub fn trans_ptr_binop<'tcx>(
in_lhs: CValue<'tcx>, in_lhs: CValue<'tcx>,
in_rhs: CValue<'tcx>, in_rhs: CValue<'tcx>,
) -> CValue<'tcx> { ) -> CValue<'tcx> {
let not_fat = match in_lhs.layout().ty.sty { let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap().ty;
ty::RawPtr(TypeAndMut { ty, mutbl: _ }) => {
ty.is_sized(fx.tcx.at(DUMMY_SP), ParamEnv::reveal_all()) if !has_ptr_meta(fx.tcx, pointee_ty) {
}
ty::FnPtr(..) => true,
_ => bug!("trans_ptr_binop on non ptr"),
};
if not_fat {
match bin_op { match bin_op {
BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => { BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => {
let lhs = in_lhs.load_scalar(fx); let lhs = in_lhs.load_scalar(fx);
@ -364,7 +359,6 @@ pub fn trans_ptr_binop<'tcx>(
} }
BinOp::Offset => { BinOp::Offset => {
let (base, offset) = (in_lhs, in_rhs.load_scalar(fx)); let (base, offset) = (in_lhs, in_rhs.load_scalar(fx));
let pointee_ty = base.layout().ty.builtin_deref(true).unwrap().ty;
let pointee_size = fx.layout_of(pointee_ty).size.bytes(); let pointee_size = fx.layout_of(pointee_ty).size.bytes();
let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64); let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64);
let base_val = base.load_scalar(fx); let base_val = base.load_scalar(fx);

View file

@ -136,7 +136,7 @@ impl<'tcx> CValue<'tcx> {
CValueInner::ByRef(addr) => { CValueInner::ByRef(addr) => {
let (a_scalar, b_scalar) = match &layout.abi { let (a_scalar, b_scalar) = match &layout.abi {
layout::Abi::ScalarPair(a, b) => (a, b), layout::Abi::ScalarPair(a, b) => (a, b),
_ => unreachable!(), _ => unreachable!("load_scalar_pair({:?})", self),
}; };
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar); let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar.clone()); let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar.clone());
@ -496,19 +496,16 @@ impl<'tcx> CPlace<'tcx> {
pub fn place_deref(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> CPlace<'tcx> { pub fn place_deref(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> CPlace<'tcx> {
let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap().ty); let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap().ty);
if !inner_layout.is_unsized() { if has_ptr_meta(fx.tcx, inner_layout.ty) {
CPlace::for_addr(self.to_cvalue(fx).load_scalar(fx), inner_layout)
} else {
let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx); let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx);
CPlace::for_addr_with_extra(addr, extra, inner_layout) CPlace::for_addr_with_extra(addr, extra, inner_layout)
} else {
CPlace::for_addr(self.to_cvalue(fx).load_scalar(fx), inner_layout)
} }
} }
pub fn write_place_ref(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>, dest: CPlace<'tcx>) { pub fn write_place_ref(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>, dest: CPlace<'tcx>) {
if !self.layout().is_unsized() { if has_ptr_meta(fx.tcx, self.layout().ty) {
let ptr = CValue::by_val(self.to_addr(fx), dest.layout());
dest.write_cvalue(fx, ptr);
} else {
let (value, extra) = self.to_addr_maybe_unsized(fx); let (value, extra) = self.to_addr_maybe_unsized(fx);
let ptr = CValue::by_val_pair( let ptr = CValue::by_val_pair(
value, value,
@ -516,6 +513,9 @@ impl<'tcx> CPlace<'tcx> {
dest.layout(), dest.layout(),
); );
dest.write_cvalue(fx, ptr); dest.write_cvalue(fx, ptr);
} else {
let ptr = CValue::by_val(self.to_addr(fx), dest.layout());
dest.write_cvalue(fx, ptr);
} }
} }