diff options
| -rw-r--r-- | src/librustc_llvm/ffi.rs | 3 | ||||
| -rw-r--r-- | src/librustc_trans/adt.rs | 9 | ||||
| -rw-r--r-- | src/librustc_trans/builder.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/common.rs | 21 | ||||
| -rw-r--r-- | src/librustc_trans/intrinsic.rs | 3 | ||||
| -rw-r--r-- | src/librustc_trans/mir/constant.rs | 104 | ||||
| -rw-r--r-- | src/librustc_trans/mir/lvalue.rs | 4 | ||||
| -rw-r--r-- | src/librustc_trans/mir/operand.rs | 14 | ||||
| -rw-r--r-- | src/test/codegen/consts.rs | 4 | ||||
| -rw-r--r-- | src/test/codegen/link_section.rs | 4 |
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.); |
