]> git.lizzy.rs Git - rust.git/commitdiff
Implement `as` casting (Misc cast kind)
authorSimonas Kazlauskas <git@kazlauskas.me>
Thu, 5 Nov 2015 11:33:06 +0000 (13:33 +0200)
committerSimonas Kazlauskas <git@kazlauskas.me>
Tue, 29 Dec 2015 18:47:18 +0000 (20:47 +0200)
src/librustc_trans/trans/mir/rvalue.rs
src/test/run-pass/mir_misc_casts.rs [new file with mode: 0644]

index 55a41201b2ba17c849236fbf26c55dd53bb2bee4..7eda6acc0abd515dd2d1c6031a1d231a2b33985c 100644 (file)
@@ -10,6 +10,7 @@
 
 use llvm::ValueRef;
 use rustc::middle::ty::{self, Ty};
+use middle::ty::cast::{CastTy, IntTy};
 use rustc::mir::repr as mir;
 
 use trans::asm;
@@ -198,7 +199,89 @@ pub fn trans_rvalue_operand(&mut self,
                             }
                         }
                     }
-                    mir::CastKind::Misc => unimplemented!()
+                    mir::CastKind::Misc if common::type_is_immediate(bcx.ccx(), operand.ty) => {
+                        debug_assert!(common::type_is_immediate(bcx.ccx(), cast_ty));
+                        let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
+                        let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
+                        let ll_t_in = type_of::arg_type_of(bcx.ccx(), operand.ty);
+                        let ll_t_out = type_of::arg_type_of(bcx.ccx(), cast_ty);
+                        let (llval, ll_t_in, signed) = if let CastTy::Int(IntTy::CEnum) = r_t_in {
+                            let repr = adt::represent_type(bcx.ccx(), operand.ty);
+                            let llval = operand.immediate();
+                            let discr = adt::trans_get_discr(bcx, &*repr, llval, None);
+                            (discr, common::val_ty(discr), adt::is_discr_signed(&*repr))
+                        } else {
+                            (operand.immediate(), ll_t_in, operand.ty.is_signed())
+                        };
+
+                        let newval = match (r_t_in, r_t_out) {
+                            (CastTy::Int(_), CastTy::Int(_)) => {
+                                let srcsz = ll_t_in.int_width();
+                                let dstsz = ll_t_out.int_width();
+                                if srcsz == dstsz {
+                                    build::BitCast(bcx, llval, ll_t_out)
+                                } else if srcsz > dstsz {
+                                    build::Trunc(bcx, llval, ll_t_out)
+                                } else if signed {
+                                    build::SExt(bcx, llval, ll_t_out)
+                                } else {
+                                    build::ZExt(bcx, llval, ll_t_out)
+                                }
+                            }
+                            (CastTy::Float, CastTy::Float) => {
+                                let srcsz = ll_t_in.float_width();
+                                let dstsz = ll_t_out.float_width();
+                                if dstsz > srcsz {
+                                    build::FPExt(bcx, llval, ll_t_out)
+                                } else if srcsz > dstsz {
+                                    build::FPTrunc(bcx, llval, ll_t_out)
+                                } else {
+                                    llval
+                                }
+                            }
+                            (CastTy::Ptr(_), CastTy::Ptr(_)) |
+                            (CastTy::FnPtr, CastTy::Ptr(_)) |
+                            (CastTy::RPtr(_), CastTy::Ptr(_)) =>
+                                build::PointerCast(bcx, llval, ll_t_out),
+                            (CastTy::Ptr(_), CastTy::Int(_)) |
+                            (CastTy::FnPtr, CastTy::Int(_)) =>
+                                build::PtrToInt(bcx, llval, ll_t_out),
+                            (CastTy::Int(_), CastTy::Ptr(_)) =>
+                                build::IntToPtr(bcx, llval, ll_t_out),
+                            (CastTy::Int(_), CastTy::Float) if signed =>
+                                build::SIToFP(bcx, llval, ll_t_out),
+                            (CastTy::Int(_), CastTy::Float) =>
+                                build::UIToFP(bcx, llval, ll_t_out),
+                            (CastTy::Float, CastTy::Int(IntTy::I)) =>
+                                build::FPToSI(bcx, llval, ll_t_out),
+                            (CastTy::Float, CastTy::Int(_)) =>
+                                build::FPToUI(bcx, llval, ll_t_out),
+                            _ => bcx.ccx().sess().bug(
+                                &format!("unsupported cast: {:?} to {:?}", operand.ty, cast_ty)
+                            )
+                        };
+                        OperandValue::Immediate(newval)
+                    }
+                    mir::CastKind::Misc => { // Casts from a fat-ptr.
+                        let ll_cast_ty = type_of::arg_type_of(bcx.ccx(), cast_ty);
+                        let ll_from_ty = type_of::arg_type_of(bcx.ccx(), operand.ty);
+                        if let OperandValue::FatPtr(data_ptr, meta_ptr) = operand.val {
+                            if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
+                                let ll_cft = ll_cast_ty.field_types();
+                                let ll_fft = ll_from_ty.field_types();
+                                let data_cast = build::PointerCast(bcx, data_ptr, ll_cft[0]);
+                                assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
+                                OperandValue::FatPtr(data_cast, meta_ptr)
+                            } else { // cast to thin-ptr
+                                // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
+                                // pointer-cast of that pointer to desired pointer type.
+                                let llval = build::PointerCast(bcx, data_ptr, ll_cast_ty);
+                                OperandValue::Immediate(llval)
+                            }
+                        } else {
+                            panic!("Unexpected non-FatPtr operand")
+                        }
+                    }
                 };
                 (bcx, OperandRef {
                     val: val,
diff --git a/src/test/run-pass/mir_misc_casts.rs b/src/test/run-pass/mir_misc_casts.rs
new file mode 100644 (file)
index 0000000..0799ffe
--- /dev/null
@@ -0,0 +1,349 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(libc, rustc_attrs)]
+
+extern crate libc;
+
+fn func(){}
+
+const STR: &'static str = "hello";
+const BSTR: &'static [u8; 5] = b"hello";
+
+#[rustc_mir]
+fn from_ptr()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, *const ()) {
+    let f = 1_usize as *const libc::FILE;
+    let c1 = f as isize;
+    let c2 = f as usize;
+    let c3 = f as i8;
+    let c4 = f as i16;
+    let c5 = f as i32;
+    let c6 = f as i64;
+    let c7 = f as u8;
+    let c8 = f as u16;
+    let c9 = f as u32;
+    let c10 = f as u64;
+    let c11 = f as *const ();
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11)
+}
+
+#[rustc_mir]
+fn from_1()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+    let c1 = 1 as isize;
+    let c2 = 1 as usize;
+    let c3 = 1 as i8;
+    let c4 = 1 as i16;
+    let c5 = 1 as i32;
+    let c6 = 1 as i64;
+    let c7 = 1 as u8;
+    let c8 = 1 as u16;
+    let c9 = 1 as u32;
+    let c10 = 1 as u64;
+    let c11 = 1 as f32;
+    let c12 = 1 as f64;
+    let c13 = 1 as *const libc::FILE;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1usize()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+    let c1 = 1_usize as isize;
+    let c2 = 1_usize as usize;
+    let c3 = 1_usize as i8;
+    let c4 = 1_usize as i16;
+    let c5 = 1_usize as i32;
+    let c6 = 1_usize as i64;
+    let c7 = 1_usize as u8;
+    let c8 = 1_usize as u16;
+    let c9 = 1_usize as u32;
+    let c10 = 1_usize as u64;
+    let c11 = 1_usize as f32;
+    let c12 = 1_usize as f64;
+    let c13 = 1_usize as *const libc::FILE;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1isize()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+    let c1 = 1_isize as isize;
+    let c2 = 1_isize as usize;
+    let c3 = 1_isize as i8;
+    let c4 = 1_isize as i16;
+    let c5 = 1_isize as i32;
+    let c6 = 1_isize as i64;
+    let c7 = 1_isize as u8;
+    let c8 = 1_isize as u16;
+    let c9 = 1_isize as u32;
+    let c10 = 1_isize as u64;
+    let c11 = 1_isize as f32;
+    let c12 = 1_isize as f64;
+    let c13 = 1_isize as *const libc::FILE;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1u8()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+    let c1 = 1_u8 as isize;
+    let c2 = 1_u8 as usize;
+    let c3 = 1_u8 as i8;
+    let c4 = 1_u8 as i16;
+    let c5 = 1_u8 as i32;
+    let c6 = 1_u8 as i64;
+    let c7 = 1_u8 as u8;
+    let c8 = 1_u8 as u16;
+    let c9 = 1_u8 as u32;
+    let c10 = 1_u8 as u64;
+    let c11 = 1_u8 as f32;
+    let c12 = 1_u8 as f64;
+    let c13 = 1_u8 as *const libc::FILE;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1i8()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+    let c1 = 1_i8 as isize;
+    let c2 = 1_i8 as usize;
+    let c3 = 1_i8 as i8;
+    let c4 = 1_i8 as i16;
+    let c5 = 1_i8 as i32;
+    let c6 = 1_i8 as i64;
+    let c7 = 1_i8 as u8;
+    let c8 = 1_i8 as u16;
+    let c9 = 1_i8 as u32;
+    let c10 = 1_i8 as u64;
+    let c11 = 1_i8 as f32;
+    let c12 = 1_i8 as f64;
+    let c13 = 1_i8 as *const libc::FILE;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1u16()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+    let c1 = 1_u16 as isize;
+    let c2 = 1_u16 as usize;
+    let c3 = 1_u16 as i8;
+    let c4 = 1_u16 as i16;
+    let c5 = 1_u16 as i32;
+    let c6 = 1_u16 as i64;
+    let c7 = 1_u16 as u8;
+    let c8 = 1_u16 as u16;
+    let c9 = 1_u16 as u32;
+    let c10 = 1_u16 as u64;
+    let c11 = 1_u16 as f32;
+    let c12 = 1_u16 as f64;
+    let c13 = 1_u16 as *const libc::FILE;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1i16()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+    let c1 = 1_i16 as isize;
+    let c2 = 1_i16 as usize;
+    let c3 = 1_i16 as i8;
+    let c4 = 1_i16 as i16;
+    let c5 = 1_i16 as i32;
+    let c6 = 1_i16 as i64;
+    let c7 = 1_i16 as u8;
+    let c8 = 1_i16 as u16;
+    let c9 = 1_i16 as u32;
+    let c10 = 1_i16 as u64;
+    let c11 = 1_i16 as f32;
+    let c12 = 1_i16 as f64;
+    let c13 = 1_i16 as *const libc::FILE;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1u32()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+    let c1 = 1_u32 as isize;
+    let c2 = 1_u32 as usize;
+    let c3 = 1_u32 as i8;
+    let c4 = 1_u32 as i16;
+    let c5 = 1_u32 as i32;
+    let c6 = 1_u32 as i64;
+    let c7 = 1_u32 as u8;
+    let c8 = 1_u32 as u16;
+    let c9 = 1_u32 as u32;
+    let c10 = 1_u32 as u64;
+    let c11 = 1_u32 as f32;
+    let c12 = 1_u32 as f64;
+    let c13 = 1_u32 as *const libc::FILE;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1i32()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+    let c1 = 1_i32 as isize;
+    let c2 = 1_i32 as usize;
+    let c3 = 1_i32 as i8;
+    let c4 = 1_i32 as i16;
+    let c5 = 1_i32 as i32;
+    let c6 = 1_i32 as i64;
+    let c7 = 1_i32 as u8;
+    let c8 = 1_i32 as u16;
+    let c9 = 1_i32 as u32;
+    let c10 = 1_i32 as u64;
+    let c11 = 1_i32 as f32;
+    let c12 = 1_i32 as f64;
+    let c13 = 1_i32 as *const libc::FILE;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1u64()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+    let c1 = 1_u64 as isize;
+    let c2 = 1_u64 as usize;
+    let c3 = 1_u64 as i8;
+    let c4 = 1_u64 as i16;
+    let c5 = 1_u64 as i32;
+    let c6 = 1_u64 as i64;
+    let c7 = 1_u64 as u8;
+    let c8 = 1_u64 as u16;
+    let c9 = 1_u64 as u32;
+    let c10 = 1_u64 as u64;
+    let c11 = 1_u64 as f32;
+    let c12 = 1_u64 as f64;
+    let c13 = 1_u64 as *const libc::FILE;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_1i64()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const libc::FILE) {
+    let c1 = 1_i64 as isize;
+    let c2 = 1_i64 as usize;
+    let c3 = 1_i64 as i8;
+    let c4 = 1_i64 as i16;
+    let c5 = 1_i64 as i32;
+    let c6 = 1_i64 as i64;
+    let c7 = 1_i64 as u8;
+    let c8 = 1_i64 as u16;
+    let c9 = 1_i64 as u32;
+    let c10 = 1_i64 as u64;
+    let c11 = 1_i64 as f32;
+    let c12 = 1_i64 as f64;
+    let c13 = 1_i64 as *const libc::FILE;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13)
+}
+
+#[rustc_mir]
+fn from_bool()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64) {
+    let c1 = true as isize;
+    let c2 = true as usize;
+    let c3 = true as i8;
+    let c4 = true as i16;
+    let c5 = true as i32;
+    let c6 = true as i64;
+    let c7 = true as u8;
+    let c8 = true as u16;
+    let c9 = true as u32;
+    let c10 = true as u64;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10)
+}
+
+#[rustc_mir]
+fn from_1f32()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64) {
+    let c1 = 1.0_f32 as isize;
+    let c2 = 1.0_f32 as usize;
+    let c3 = 1.0_f32 as i8;
+    let c4 = 1.0_f32 as i16;
+    let c5 = 1.0_f32 as i32;
+    let c6 = 1.0_f32 as i64;
+    let c7 = 1.0_f32 as u8;
+    let c8 = 1.0_f32 as u16;
+    let c9 = 1.0_f32 as u32;
+    let c10 = 1.0_f32 as u64;
+    let c11 = 1.0_f32 as f32;
+    let c12 = 1.0_f32 as f64;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12)
+}
+
+#[rustc_mir]
+fn from_1f64()
+-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64) {
+    let c1 = 1.0f64 as isize;
+    let c2 = 1.0f64 as usize;
+    let c3 = 1.0f64 as i8;
+    let c4 = 1.0f64 as i16;
+    let c5 = 1.0f64 as i32;
+    let c6 = 1.0f64 as i64;
+    let c7 = 1.0f64 as u8;
+    let c8 = 1.0f64 as u16;
+    let c9 = 1.0f64 as u32;
+    let c10 = 1.0f64 as u64;
+    let c11 = 1.0f64 as f32;
+    let c12 = 1.0f64 as f64;
+    (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12)
+}
+
+#[rustc_mir]
+fn other_casts()
+-> (*const u8, *const isize, *const u8, *const u8) {
+    let c1 = func as *const u8;
+    let c2 = c1 as *const isize;
+
+    let r = &42u32;
+    let _ = r as *const u32;
+
+    // fat-ptr -> fat-ptr -> fat-raw-ptr -> thin-ptr
+    let c3 = STR as &str as *const str as *const u8;
+
+    let c4 = BSTR as *const [u8] as *const [u16] as *const u8;
+    (c1, c2, c3, c4)
+}
+
+pub fn assert_eq_13(l: (isize, usize, i8, i16, i32, i64, u8,
+                        u16, u32, u64, f32, f64, *const libc::FILE),
+                    r: (isize, usize, i8, i16, i32, i64, u8,
+                        u16, u32, u64, f32, f64, *const libc::FILE)) -> bool {
+    let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13) = l;
+    let (r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13) = r;
+    l1 == r1 && l2 == r2 && l3 == r3 && l4 == r4 && l5 == r5 && l6 == r6 && l7 == r7 &&
+    l8 == r8 && l9 == r9 && l10 == r10 && l11 == r11 && l12 == r12 && l13 == r13
+}
+
+
+pub fn main() {
+    let f = 1_usize as *const libc::FILE;
+    let t13 = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.0, 1.0, f);
+    let t12 = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.0, 1.0);
+    assert_eq_13(from_1(), t13);
+    assert_eq_13(from_1usize(), t13);
+    assert_eq_13(from_1isize(), t13);
+    assert_eq_13(from_1u8(), t13);
+    assert_eq_13(from_1i8(), t13);
+    assert_eq_13(from_1u16(), t13);
+    assert_eq_13(from_1i16(), t13);
+    assert_eq_13(from_1u32(), t13);
+    assert_eq_13(from_1i32(), t13);
+    assert_eq_13(from_1u64(), t13);
+    assert_eq_13(from_1i64(), t13);
+    assert_eq!(from_1f32(), t12);
+    assert_eq!(from_1f64(), t12);
+
+    assert_eq!(from_ptr(), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 as *const ()));
+    assert_eq!(from_bool(), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
+
+    assert_eq!(other_casts(), (func as *const u8, func as *const isize,
+                               STR as *const str as *const u8, BSTR as *const [u8] as *const u8));
+}