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