about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_llvm/ffi.rs3
-rw-r--r--src/librustc_trans/adt.rs9
-rw-r--r--src/librustc_trans/builder.rs2
-rw-r--r--src/librustc_trans/common.rs21
-rw-r--r--src/librustc_trans/intrinsic.rs3
-rw-r--r--src/librustc_trans/mir/constant.rs104
-rw-r--r--src/librustc_trans/mir/lvalue.rs4
-rw-r--r--src/librustc_trans/mir/operand.rs14
-rw-r--r--src/test/codegen/consts.rs4
-rw-r--r--src/test/codegen/link_section.rs4
10 files changed, 68 insertions, 100 deletions
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
index 48f8094f98d..d800129b0c0 100644
--- a/src/librustc_llvm/ffi.rs
+++ b/src/librustc_llvm/ffi.rs
@@ -611,10 +611,7 @@ extern "C" {
     pub fn LLVMConstNull(Ty: TypeRef) -> ValueRef;
     pub fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef;
     pub fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef;
-    // only for isize/vector
     pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef;
-    pub fn LLVMIsNull(Val: ValueRef) -> Bool;
-    pub fn LLVMIsUndef(Val: ValueRef) -> Bool;
 
     // Operations on metadata
     pub fn LLVMMDStringInContext(C: ContextRef, Str: *const c_char, SLen: c_uint) -> ValueRef;
diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs
index b5b90753553..9d693e098cf 100644
--- a/src/librustc_trans/adt.rs
+++ b/src/librustc_trans/adt.rs
@@ -198,9 +198,14 @@ fn union_fill(cx: &CrateContext, size: Size, align: Align) -> Type {
     Type::array(&elem_ty, size / abi_align)
 }
 
-// Lookup `Struct::memory_index` and double it to account for padding
+/// Double an index to account for padding.
+pub fn memory_index_to_gep(index: usize) -> usize {
+    index * 2
+}
+
+/// Lookup `Struct::memory_index`, double it to account for padding.
 pub fn struct_llfields_index(variant: &layout::Struct, index: usize) -> usize {
-    (variant.memory_index[index] as usize) << 1
+    memory_index_to_gep(variant.memory_index[index] as usize)
 }
 
 pub fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index c8d8984122f..2b632ba6f26 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -1150,14 +1150,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
     pub fn add_case(&self, s: ValueRef, on_val: ValueRef, dest: BasicBlockRef) {
         unsafe {
-            if llvm::LLVMIsUndef(s) == llvm::True { return; }
             llvm::LLVMAddCase(s, on_val, dest)
         }
     }
 
     pub fn add_incoming_to_phi(&self, phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
         unsafe {
-            if llvm::LLVMIsUndef(phi) == llvm::True { return; }
             llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
         }
     }
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index e3ee8f7c75a..659ce0f7f9f 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -356,13 +356,13 @@ pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef {
     }
 }
 
-pub fn const_get_elt(v: ValueRef, us: &[c_uint])
-              -> ValueRef {
+pub fn const_get_elt(v: ValueRef, i: usize) -> ValueRef {
     unsafe {
+        let us = &[i as c_uint];
         let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
 
-        debug!("const_get_elt(v={:?}, us={:?}, r={:?})",
-               Value(v), us, Value(r));
+        debug!("const_get_elt(v={:?}, i={}, r={:?})",
+               Value(v), i, Value(r));
 
         r
     }
@@ -402,19 +402,6 @@ pub fn const_to_opt_u128(v: ValueRef, sign_ext: bool) -> Option<u128> {
     }
 }
 
-pub fn is_undef(val: ValueRef) -> bool {
-    unsafe {
-        llvm::LLVMIsUndef(val) != False
-    }
-}
-
-#[allow(dead_code)] // potentially useful
-pub fn is_null(val: ValueRef) -> bool {
-    unsafe {
-        llvm::LLVMIsNull(val) != False
-    }
-}
-
 pub fn langcall(tcx: TyCtxt,
                 span: Option<Span>,
                 msg: &str,
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index c66a8ae2fcc..711854e28a8 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -11,7 +11,6 @@
 #![allow(non_upper_case_globals)]
 
 use intrinsics::{self, Intrinsic};
-use libc;
 use llvm;
 use llvm::{ValueRef};
 use abi::{Abi, FnType};
@@ -1072,7 +1071,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
         let indices: Option<Vec<_>> = (0..n)
             .map(|i| {
                 let arg_idx = i;
-                let val = const_get_elt(vector, &[i as libc::c_uint]);
+                let val = const_get_elt(vector, i);
                 match const_to_opt_u128(val, true) {
                     None => {
                         emit_error!("shuffle index #{} is not a constant", arg_idx);
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 57c131a106b..fa0558faad2 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -29,7 +29,7 @@ use callee;
 use builder::Builder;
 use common::{self, CrateContext, const_get_elt, val_ty};
 use common::{C_array, C_bool, C_bytes, C_int, C_uint, C_big_integral, C_u32, C_u64};
-use common::{C_null, C_struct, C_str_slice, C_undef, C_usize, C_vector, is_undef};
+use common::{C_null, C_struct, C_str_slice, C_undef, C_usize, C_vector};
 use common::const_to_opt_u128;
 use consts;
 use type_of;
@@ -55,7 +55,7 @@ pub struct Const<'tcx> {
     pub ty: Ty<'tcx>
 }
 
-impl<'tcx> Const<'tcx> {
+impl<'a, 'tcx> Const<'tcx> {
     pub fn new(llval: ValueRef, ty: Ty<'tcx>) -> Const<'tcx> {
         Const {
             llval,
@@ -63,8 +63,7 @@ impl<'tcx> Const<'tcx> {
         }
     }
 
-    pub fn from_constint<'a>(ccx: &CrateContext<'a, 'tcx>, ci: &ConstInt)
-    -> Const<'tcx> {
+    pub fn from_constint(ccx: &CrateContext<'a, 'tcx>, ci: &ConstInt) -> Const<'tcx> {
         let tcx = ccx.tcx();
         let (llval, ty) = match *ci {
             I8(v) => (C_int(Type::i8(ccx), v as i64), tcx.types.i8),
@@ -84,10 +83,10 @@ impl<'tcx> Const<'tcx> {
     }
 
     /// Translate ConstVal into a LLVM constant value.
-    pub fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>,
-                             cv: &ConstVal,
-                             ty: Ty<'tcx>)
-                             -> Const<'tcx> {
+    pub fn from_constval(ccx: &CrateContext<'a, 'tcx>,
+                         cv: &ConstVal,
+                         ty: Ty<'tcx>)
+                         -> Const<'tcx> {
         let llty = type_of::type_of(ccx, ty);
         let val = match *cv {
             ConstVal::Float(v) => {
@@ -104,7 +103,7 @@ impl<'tcx> Const<'tcx> {
                 consts::addr_of(ccx, C_bytes(ccx, v.data), ccx.align_of(ty), "byte_str")
             }
             ConstVal::Char(c) => C_uint(Type::char(ccx), c as u64),
-            ConstVal::Function(..) => C_null(llty),
+            ConstVal::Function(..) => C_undef(llty),
             ConstVal::Variant(_) |
             ConstVal::Aggregate(..) |
             ConstVal::Unevaluated(..) => {
@@ -117,15 +116,25 @@ impl<'tcx> Const<'tcx> {
         Const::new(val, ty)
     }
 
-    fn get_pair(&self) -> (ValueRef, ValueRef) {
-        (const_get_elt(self.llval, &[0]),
-         const_get_elt(self.llval, &[1]))
+    fn get_field(&self, ccx: &CrateContext<'a, 'tcx>, i: usize) -> ValueRef {
+        let layout = ccx.layout_of(self.ty);
+        let ix = if let layout::Univariant { ref variant, .. } = *layout {
+            adt::struct_llfields_index(variant, i)
+        } else {
+            i
+        };
+
+        const_get_elt(self.llval, ix)
+    }
+
+    fn get_pair(&self, ccx: &CrateContext<'a, 'tcx>) -> (ValueRef, ValueRef) {
+        (self.get_field(ccx, 0), self.get_field(ccx, 1))
     }
 
-    fn get_fat_ptr(&self) -> (ValueRef, ValueRef) {
+    fn get_fat_ptr(&self, ccx: &CrateContext<'a, 'tcx>) -> (ValueRef, ValueRef) {
         assert_eq!(abi::FAT_PTR_ADDR, 0);
         assert_eq!(abi::FAT_PTR_EXTRA, 1);
-        self.get_pair()
+        self.get_pair(ccx)
     }
 
     fn as_lvalue(&self) -> ConstLvalue<'tcx> {
@@ -136,12 +145,12 @@ impl<'tcx> Const<'tcx> {
         }
     }
 
-    pub fn to_operand<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> {
+    pub fn to_operand(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> {
         let llty = type_of::immediate_type_of(ccx, self.ty);
         let llvalty = val_ty(self.llval);
 
         let val = if llty == llvalty && common::type_is_imm_pair(ccx, self.ty) {
-            let (a, b) = self.get_pair();
+            let (a, b) = self.get_pair(ccx);
             OperandValue::Pair(a, b)
         } else if llty == llvalty && common::type_is_immediate(ccx, self.ty) {
             // If the types match, we can use the value directly.
@@ -438,7 +447,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                         let (base, extra) = if !has_metadata {
                             (base.llval, ptr::null_mut())
                         } else {
-                            base.get_fat_ptr()
+                            base.get_fat_ptr(self.ccx)
                         };
                         if self.ccx.statics().borrow().contains_key(&base) {
                             (Base::Static(base), extra)
@@ -464,32 +473,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                         }
                     }
                     mir::ProjectionElem::Field(ref field, _) => {
-                        // Extract field of struct-like const, skipping our alignment padding.
-                        let mut ix = field.index();
-                        let layout = self.ccx.layout_of(tr_base.ty);
-                        if let layout::Univariant { ref variant, .. } = *layout {
-                            ix = variant.memory_index[ix] as usize;
-                        }
-
-                        // Get the ix-th non-undef element of the struct.
-                        let mut real_ix = 0; // actual position in the struct
-                        let mut ix = ix; // logical index relative to real_ix
-                        let mut llprojected;
-                        loop {
-                            loop {
-                                llprojected = const_get_elt(base.llval, &[real_ix]);
-                                if !is_undef(llprojected) {
-                                    break;
-                                }
-                                real_ix = real_ix + 1;
-                            }
-                            if ix == 0 {
-                                break;
-                            }
-                            ix = ix - 1;
-                            real_ix = real_ix + 1;
-                        }
-
+                        let llprojected = base.get_field(self.ccx, field.index());
                         let llextra = if !has_metadata {
                             ptr::null_mut()
                         } else {
@@ -510,7 +494,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                         // Produce an undef instead of a LLVM assertion on OOB.
                         let len = common::const_to_uint(tr_base.len(self.ccx));
                         let llelem = if iv < len as u128 {
-                            const_get_elt(base.llval, &[iv as u32])
+                            const_get_elt(base.llval, iv as usize)
                         } else {
                             C_undef(type_of::type_of(self.ccx, projected_ty))
                         };
@@ -680,7 +664,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                             // to use a different vtable. In that case, we want to
                             // load out the original data pointer so we can repackage
                             // it.
-                            let (base, extra) = operand.get_fat_ptr();
+                            let (base, extra) = operand.get_fat_ptr(self.ccx);
                             (base, Some(extra))
                         } else {
                             (operand.llval, None)
@@ -755,7 +739,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                         let ll_cast_ty = type_of::immediate_type_of(self.ccx, cast_ty);
                         let ll_from_ty = type_of::immediate_type_of(self.ccx, operand.ty);
                         if common::type_is_fat_ptr(self.ccx, operand.ty) {
-                            let (data_ptr, meta_ptr) = operand.get_fat_ptr();
+                            let (data_ptr, meta_ptr) = operand.get_fat_ptr(self.ccx);
                             if common::type_is_fat_ptr(self.ccx, cast_ty) {
                                 let ll_cft = ll_cast_ty.field_types();
                                 let ll_fft = ll_from_ty.field_types();
@@ -833,8 +817,10 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
 
                 match const_scalar_checked_binop(tcx, op, lhs, rhs, ty) {
                     Some((llval, of)) => {
-                        let llof = C_bool(self.ccx, of);
-                        Const::new(C_struct(self.ccx, &[llval, llof], false), binop_ty)
+                        trans_const_adt(self.ccx, binop_ty, &mir::AggregateKind::Tuple, &[
+                            Const::new(llval, val_ty),
+                            Const::new(C_bool(self.ccx, of), tcx.types.bool)
+                        ])
                     }
                     None => {
                         span_bug!(span, "{:?} got non-integer operands: {:?} and {:?}",
@@ -1142,13 +1128,10 @@ fn trans_const_adt<'a, 'tcx>(
         }
         layout::UntaggedUnion { ref variants, .. }=> {
             assert_eq!(variant_index, 0);
-            let mut contents = vec![vals[0].llval];
-
-            let offset = ccx.size_of(vals[0].ty);
-            let size = variants.stride();
-            if offset != size {
-                contents.push(padding(ccx, size - offset));
-            }
+            let contents = [
+                vals[0].llval,
+                padding(ccx, variants.stride() - ccx.size_of(vals[0].ty))
+            ];
 
             Const::new(C_struct(ccx, &contents, variants.packed), t)
         }
@@ -1203,19 +1186,20 @@ fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let parts = st.field_index_by_increasing_offset().map(|i| {
         (vals[i], st.offsets[i])
     });
+    let mut first_field = true;
     for (val, target_offset) in parts {
-        if offset < target_offset {
+        if first_field {
+            first_field = false;
+            assert_eq!(target_offset.bytes(), 0);
+        } else {
             cfields.push(padding(ccx, target_offset - offset));
         }
-        assert!(!is_undef(val.llval));
         cfields.push(val.llval);
         offset = target_offset + ccx.size_of(val.ty);
     }
 
     let size = layout.size(ccx);
-    if offset < size {
-        cfields.push(padding(ccx, size - offset));
-    }
+    cfields.push(padding(ccx, size - offset));
 
     Const::new(C_struct(ccx, &cfields, st.packed), layout.ty)
 }
diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs
index 376d42c71ad..a0cab01b007 100644
--- a/src/librustc_trans/mir/lvalue.rs
+++ b/src/librustc_trans/mir/lvalue.rs
@@ -252,7 +252,9 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
 
     // Double index to account for padding (FieldPath already uses `Struct::memory_index`)
     fn gepi_struct_llfields_path(self, bcx: &Builder, discrfield: &layout::FieldPath) -> ValueRef {
-        let path = discrfield.iter().map(|&i| (i as usize) << 1).collect::<Vec<_>>();
+        let path = discrfield.iter().map(|&i| {
+            adt::memory_index_to_gep(i as usize)
+        }).collect::<Vec<_>>();
         bcx.gepi(self.llval, &path)
     }
 
diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs
index 47350d07125..60f585f4bd9 100644
--- a/src/librustc_trans/mir/operand.rs
+++ b/src/librustc_trans/mir/operand.rs
@@ -17,7 +17,7 @@ use rustc_data_structures::indexed_vec::Idx;
 
 use adt;
 use base;
-use common::{self, CrateContext, C_null};
+use common::{self, CrateContext, C_undef};
 use builder::Builder;
 use value::Value;
 use type_of;
@@ -93,9 +93,9 @@ impl<'a, 'tcx> OperandRef<'tcx> {
                 (0, 1)
             };
             let fields = llty.field_types();
-            OperandValue::Pair(C_null(fields[ix0]), C_null(fields[ix1]))
+            OperandValue::Pair(C_undef(fields[ix0]), C_undef(fields[ix1]))
         } else {
-            OperandValue::Immediate(C_null(llty))
+            OperandValue::Immediate(C_undef(llty))
         };
         OperandRef {
             val,
@@ -134,14 +134,10 @@ impl<'a, 'tcx> OperandRef<'tcx> {
         if let OperandValue::Pair(a, b) = self.val {
             // Reconstruct the immediate aggregate.
             let llty = type_of::type_of(bcx.ccx, self.ty);
-            let mut llpair = common::C_undef(llty);
+            let mut llpair = C_undef(llty);
             let elems = [a, b];
             for i in 0..2 {
-                let mut elem = elems[i];
-                // Extend boolean i1's to i8.
-                if common::val_ty(elem) == Type::i1(bcx.ccx) {
-                    elem = bcx.zext(elem, Type::i8(bcx.ccx));
-                }
+                let elem = base::from_immediate(bcx, elems[i]);
                 let layout = bcx.ccx.layout_of(self.ty);
                 let i = if let Layout::Univariant { ref variant, .. } = *layout {
                     adt::struct_llfields_index(variant, i)
diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs
index 33b4221b733..a75b8f3992d 100644
--- a/src/test/codegen/consts.rs
+++ b/src/test/codegen/consts.rs
@@ -54,7 +54,7 @@ pub fn inline_enum_const() -> E<i8, i16> {
 #[no_mangle]
 pub fn low_align_const() -> E<i16, [i16; 3]> {
 // Check that low_align_const and high_align_const use the same constant
-// CHECK: load {{.*}} bitcast ({ i16, i16, [4 x i8] }** [[LOW_HIGH_REF]]
+// CHECK: load {{.*}} bitcast ({ i16, [0 x i8], i16, [4 x i8] }** [[LOW_HIGH_REF]]
     *&E::A(0)
 }
 
@@ -62,6 +62,6 @@ pub fn low_align_const() -> E<i16, [i16; 3]> {
 #[no_mangle]
 pub fn high_align_const() -> E<i16, i32> {
 // Check that low_align_const and high_align_const use the same constant
-// CHECK: load {{.*}} bitcast ({ i16, i16, [4 x i8] }** [[LOW_HIGH_REF]]
+// CHECK: load {{.*}} bitcast ({ i16, [0 x i8], i16, [4 x i8] }** [[LOW_HIGH_REF]]
     *&E::A(0)
 }
diff --git a/src/test/codegen/link_section.rs b/src/test/codegen/link_section.rs
index 98214dc5c6f..1879002e7f3 100644
--- a/src/test/codegen/link_section.rs
+++ b/src/test/codegen/link_section.rs
@@ -22,12 +22,12 @@ pub enum E {
     B(f32)
 }
 
-// CHECK: @VAR2 = constant {{.*}} { i32 0, i32 666 }, section ".test_two"
+// CHECK: @VAR2 = constant {{.*}}, section ".test_two"
 #[no_mangle]
 #[link_section = ".test_two"]
 pub static VAR2: E = E::A(666);
 
-// CHECK: @VAR3 = constant {{.*}} { i32 1, float 1.000000e+00 }, section ".test_three"
+// CHECK: @VAR3 = constant {{.*}}, section ".test_three"
 #[no_mangle]
 #[link_section = ".test_three"]
 pub static VAR3: E = E::B(1.);