Skip to content

Commit feab2ae

Browse files
committed
Implement as casting (Misc cast kind)
1 parent 3150ddd commit feab2ae

File tree

2 files changed

+433
-1
lines changed

2 files changed

+433
-1
lines changed

src/librustc_trans/trans/mir/rvalue.rs

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use llvm::ValueRef;
1212
use rustc::middle::ty::{self, Ty};
13+
use middle::ty::cast::{CastTy, IntTy};
1314
use rustc::mir::repr as mir;
1415

1516
use trans::asm;
@@ -198,7 +199,89 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
198199
}
199200
}
200201
}
201-
mir::CastKind::Misc => unimplemented!()
202+
mir::CastKind::Misc if common::type_is_immediate(bcx.ccx(), operand.ty) => {
203+
debug_assert!(common::type_is_immediate(bcx.ccx(), cast_ty));
204+
let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
205+
let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
206+
let ll_t_in = type_of::arg_type_of(bcx.ccx(), operand.ty);
207+
let ll_t_out = type_of::arg_type_of(bcx.ccx(), cast_ty);
208+
let (llval, ll_t_in, signed) = if let CastTy::Int(IntTy::CEnum) = r_t_in {
209+
let repr = adt::represent_type(bcx.ccx(), operand.ty);
210+
let llval = operand.immediate();
211+
let discr = adt::trans_get_discr(bcx, &*repr, llval, None);
212+
(discr, common::val_ty(discr), adt::is_discr_signed(&*repr))
213+
} else {
214+
(operand.immediate(), ll_t_in, operand.ty.is_signed())
215+
};
216+
217+
let newval = match (r_t_in, r_t_out) {
218+
(CastTy::Int(_), CastTy::Int(_)) => {
219+
let srcsz = ll_t_in.int_width();
220+
let dstsz = ll_t_out.int_width();
221+
if srcsz == dstsz {
222+
build::BitCast(bcx, llval, ll_t_out)
223+
} else if srcsz > dstsz {
224+
build::Trunc(bcx, llval, ll_t_out)
225+
} else if signed {
226+
build::SExt(bcx, llval, ll_t_out)
227+
} else {
228+
build::ZExt(bcx, llval, ll_t_out)
229+
}
230+
}
231+
(CastTy::Float, CastTy::Float) => {
232+
let srcsz = ll_t_in.float_width();
233+
let dstsz = ll_t_out.float_width();
234+
if dstsz > srcsz {
235+
build::FPExt(bcx, llval, ll_t_out)
236+
} else if srcsz > dstsz {
237+
build::FPTrunc(bcx, llval, ll_t_out)
238+
} else {
239+
llval
240+
}
241+
}
242+
(CastTy::Ptr(_), CastTy::Ptr(_)) |
243+
(CastTy::FnPtr, CastTy::Ptr(_)) |
244+
(CastTy::RPtr(_), CastTy::Ptr(_)) =>
245+
build::PointerCast(bcx, llval, ll_t_out),
246+
(CastTy::Ptr(_), CastTy::Int(_)) |
247+
(CastTy::FnPtr, CastTy::Int(_)) =>
248+
build::PtrToInt(bcx, llval, ll_t_out),
249+
(CastTy::Int(_), CastTy::Ptr(_)) =>
250+
build::IntToPtr(bcx, llval, ll_t_out),
251+
(CastTy::Int(_), CastTy::Float) if signed =>
252+
build::SIToFP(bcx, llval, ll_t_out),
253+
(CastTy::Int(_), CastTy::Float) =>
254+
build::UIToFP(bcx, llval, ll_t_out),
255+
(CastTy::Float, CastTy::Int(IntTy::I)) =>
256+
build::FPToSI(bcx, llval, ll_t_out),
257+
(CastTy::Float, CastTy::Int(_)) =>
258+
build::FPToUI(bcx, llval, ll_t_out),
259+
_ => bcx.ccx().sess().bug(
260+
&format!("unsupported cast: {:?} to {:?}", operand.ty, cast_ty)
261+
)
262+
};
263+
OperandValue::Immediate(newval)
264+
}
265+
mir::CastKind::Misc => { // Casts from a fat-ptr.
266+
let ll_cast_ty = type_of::arg_type_of(bcx.ccx(), cast_ty);
267+
let ll_from_ty = type_of::arg_type_of(bcx.ccx(), operand.ty);
268+
if let OperandValue::FatPtr(data_ptr, meta_ptr) = operand.val {
269+
if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
270+
let ll_cft = ll_cast_ty.field_types();
271+
let ll_fft = ll_from_ty.field_types();
272+
let data_cast = build::PointerCast(bcx, data_ptr, ll_cft[0]);
273+
assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
274+
OperandValue::FatPtr(data_cast, meta_ptr)
275+
} else { // cast to thin-ptr
276+
// Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
277+
// pointer-cast of that pointer to desired pointer type.
278+
let llval = build::PointerCast(bcx, data_ptr, ll_cast_ty);
279+
OperandValue::Immediate(llval)
280+
}
281+
} else {
282+
panic!("Unexpected non-FatPtr operand")
283+
}
284+
}
202285
};
203286
(bcx, OperandRef {
204287
val: val,

0 commit comments

Comments
 (0)